From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- sw/source/uibase/app/appenv.cxx | 493 ++ sw/source/uibase/app/appenv.hxx | 23 + sw/source/uibase/app/apphdl.cxx | 1077 ++++ sw/source/uibase/app/applab.cxx | 393 ++ sw/source/uibase/app/appopt.cxx | 499 ++ sw/source/uibase/app/docsh.cxx | 1412 +++++ sw/source/uibase/app/docsh2.cxx | 1745 ++++++ sw/source/uibase/app/docshdrw.cxx | 100 + sw/source/uibase/app/docshini.cxx | 699 +++ sw/source/uibase/app/docst.cxx | 1547 +++++ sw/source/uibase/app/docstyle.cxx | 3220 ++++++++++ sw/source/uibase/app/mainwn.cxx | 133 + sw/source/uibase/app/swdll.cxx | 180 + sw/source/uibase/app/swdllimpl.hxx | 45 + sw/source/uibase/app/swmodul1.cxx | 692 +++ sw/source/uibase/app/swmodule.cxx | 403 ++ sw/source/uibase/app/swwait.cxx | 84 + sw/source/uibase/chrdlg/ccoll.cxx | 160 + sw/source/uibase/config/StoredChapterNumbering.cxx | 476 ++ sw/source/uibase/config/barcfg.cxx | 124 + sw/source/uibase/config/caption.cxx | 39 + sw/source/uibase/config/cfgitems.cxx | 245 + sw/source/uibase/config/dbconfig.cxx | 99 + sw/source/uibase/config/fontcfg.cxx | 309 + sw/source/uibase/config/modcfg.cxx | 1334 ++++ sw/source/uibase/config/prtopt.cxx | 168 + sw/source/uibase/config/uinums.cxx | 260 + sw/source/uibase/config/usrpref.cxx | 599 ++ sw/source/uibase/config/viewopt.cxx | 582 ++ sw/source/uibase/dbui/README | 48 + sw/source/uibase/dbui/dbmgr.cxx | 3366 ++++++++++ sw/source/uibase/dbui/dbtree.cxx | 435 ++ sw/source/uibase/dbui/dbui.cxx | 88 + sw/source/uibase/dbui/maildispatcher.cxx | 248 + sw/source/uibase/dbui/mailmergehelper.cxx | 832 +++ sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx | 422 ++ sw/source/uibase/dbui/mmconfigitem.cxx | 1711 ++++++ .../uibase/dialog/SwSpellDialogChildWindow.cxx | 827 +++ sw/source/uibase/dialog/regionsw.cxx | 209 + sw/source/uibase/dialog/swabstdlg.cxx | 55 + sw/source/uibase/dialog/swwrtshitem.cxx | 40 + sw/source/uibase/dialog/watermarkdialog.cxx | 106 + sw/source/uibase/dialog/wordcountwrapper.cxx | 48 + sw/source/uibase/dochdl/gloshdl.cxx | 699 +++ sw/source/uibase/dochdl/swdtflvr.cxx | 4349 +++++++++++++ sw/source/uibase/docvw/AnchorOverlayObject.cxx | 382 ++ sw/source/uibase/docvw/AnchorOverlayObject.hxx | 123 + sw/source/uibase/docvw/AnnotationMenuButton.cxx | 216 + sw/source/uibase/docvw/AnnotationMenuButton.hxx | 54 + sw/source/uibase/docvw/AnnotationWin.cxx | 507 ++ sw/source/uibase/docvw/AnnotationWin2.cxx | 1624 +++++ sw/source/uibase/docvw/DashedLine.cxx | 95 + sw/source/uibase/docvw/FrameControlsManager.cxx | 217 + sw/source/uibase/docvw/HeaderFooterWin.cxx | 521 ++ sw/source/uibase/docvw/OverlayRanges.cxx | 178 + sw/source/uibase/docvw/OverlayRanges.hxx | 75 + sw/source/uibase/docvw/PageBreakWin.cxx | 469 ++ sw/source/uibase/docvw/PostItMgr.cxx | 2456 ++++++++ sw/source/uibase/docvw/ShadowOverlayObject.cxx | 237 + sw/source/uibase/docvw/ShadowOverlayObject.hxx | 66 + sw/source/uibase/docvw/SidebarScrollBar.cxx | 73 + sw/source/uibase/docvw/SidebarScrollBar.hxx | 50 + sw/source/uibase/docvw/SidebarTxtControl.cxx | 446 ++ sw/source/uibase/docvw/SidebarTxtControl.hxx | 77 + sw/source/uibase/docvw/SidebarTxtControlAcc.cxx | 271 + sw/source/uibase/docvw/SidebarTxtControlAcc.hxx | 46 + sw/source/uibase/docvw/SidebarWinAcc.cxx | 144 + sw/source/uibase/docvw/SidebarWinAcc.hxx | 56 + sw/source/uibase/docvw/UnfloatTableButton.cxx | 233 + sw/source/uibase/docvw/edtdd.cxx | 495 ++ sw/source/uibase/docvw/edtwin.cxx | 6429 ++++++++++++++++++++ sw/source/uibase/docvw/edtwin2.cxx | 441 ++ sw/source/uibase/docvw/edtwin3.cxx | 176 + sw/source/uibase/docvw/frmsidebarwincontainer.cxx | 172 + sw/source/uibase/docvw/frmsidebarwincontainer.hxx | 64 + sw/source/uibase/docvw/romenu.cxx | 343 ++ sw/source/uibase/docvw/romenu.hxx | 82 + sw/source/uibase/docvw/srcedtw.cxx | 995 +++ sw/source/uibase/envelp/envimg.cxx | 334 + sw/source/uibase/envelp/labelcfg.cxx | 333 + sw/source/uibase/envelp/labimg.cxx | 463 ++ sw/source/uibase/envelp/syncbtn.cxx | 87 + sw/source/uibase/fldui/fldmgr.cxx | 1850 ++++++ sw/source/uibase/fldui/fldwrap.cxx | 131 + sw/source/uibase/fldui/xfldui.cxx | 162 + sw/source/uibase/frmdlg/colex.cxx | 607 ++ sw/source/uibase/frmdlg/colmgr.cxx | 161 + sw/source/uibase/frmdlg/frmmgr.cxx | 613 ++ sw/source/uibase/globdoc/globdoc.cxx | 64 + sw/source/uibase/inc/DashedLine.hxx | 29 + sw/source/uibase/inc/DateFormFieldDialog.hxx | 58 + sw/source/uibase/inc/DropDownFieldDialog.hxx | 66 + sw/source/uibase/inc/DropDownFormFieldDialog.hxx | 68 + sw/source/uibase/inc/FrameControl.hxx | 72 + sw/source/uibase/inc/FrameControlsManager.hxx | 53 + sw/source/uibase/inc/HeaderFooterWin.hxx | 73 + sw/source/uibase/inc/PageBreakWin.hxx | 66 + sw/source/uibase/inc/SidebarWindowsConsts.hxx | 33 + sw/source/uibase/inc/SwSpellDialogChildWindow.hxx | 67 + sw/source/uibase/inc/SwXFilterOptions.hxx | 81 + sw/source/uibase/inc/UnfloatTableButton.hxx | 46 + sw/source/uibase/inc/abstract.hxx | 39 + sw/source/uibase/inc/addrdlg.hxx | 32 + sw/source/uibase/inc/annotsh.hxx | 80 + sw/source/uibase/inc/ascfldlg.hxx | 65 + sw/source/uibase/inc/autoformatpreview.hxx | 82 + sw/source/uibase/inc/barcfg.hxx | 46 + sw/source/uibase/inc/basesh.hxx | 117 + sw/source/uibase/inc/beziersh.hxx | 42 + sw/source/uibase/inc/bmpwin.hxx | 53 + sw/source/uibase/inc/bookctrl.hxx | 45 + sw/source/uibase/inc/bookmark.hxx | 112 + sw/source/uibase/inc/break.hxx | 64 + sw/source/uibase/inc/caption.hxx | 89 + sw/source/uibase/inc/cfgitems.hxx | 163 + sw/source/uibase/inc/changedb.hxx | 60 + sw/source/uibase/inc/chartins.hxx | 37 + sw/source/uibase/inc/chldwrap.hxx | 47 + sw/source/uibase/inc/chrdlg.hxx | 74 + sw/source/uibase/inc/chrdlgmodes.hxx | 20 + sw/source/uibase/inc/cnttab.hxx | 57 + sw/source/uibase/inc/colex.hxx | 107 + sw/source/uibase/inc/colmgr.hxx | 126 + sw/source/uibase/inc/column.hxx | 206 + sw/source/uibase/inc/conarc.hxx | 43 + sw/source/uibase/inc/concustomshape.hxx | 57 + sw/source/uibase/inc/condedit.hxx | 70 + sw/source/uibase/inc/conform.hxx | 38 + sw/source/uibase/inc/conpoly.hxx | 38 + sw/source/uibase/inc/conrect.hxx | 45 + sw/source/uibase/inc/content.hxx | 186 + sw/source/uibase/inc/conttree.hxx | 383 ++ sw/source/uibase/inc/convert.hxx | 69 + sw/source/uibase/inc/cption.hxx | 83 + sw/source/uibase/inc/dbconfig.hxx | 48 + sw/source/uibase/inc/dbinsdlg.hxx | 161 + sw/source/uibase/inc/dbtree.hxx | 67 + sw/source/uibase/inc/dbui.hxx | 70 + sw/source/uibase/inc/docfnote.hxx | 40 + sw/source/uibase/inc/docstdlg.hxx | 61 + sw/source/uibase/inc/drawbase.hxx | 73 + sw/source/uibase/inc/drawsh.hxx | 56 + sw/source/uibase/inc/drformsh.hxx | 45 + sw/source/uibase/inc/drpcps.hxx | 165 + sw/source/uibase/inc/drwbassh.hxx | 55 + sw/source/uibase/inc/drwtxtsh.hxx | 84 + sw/source/uibase/inc/dselect.hxx | 35 + sw/source/uibase/inc/edtdd.hxx | 19 + sw/source/uibase/inc/edtwin.hxx | 301 + sw/source/uibase/inc/envimg.hxx | 89 + sw/source/uibase/inc/envlop.hxx | 122 + sw/source/uibase/inc/fldedt.hxx | 59 + sw/source/uibase/inc/fldmgr.hxx | 203 + sw/source/uibase/inc/fldtdlg.hxx | 62 + sw/source/uibase/inc/fldwrap.hxx | 57 + sw/source/uibase/inc/fontcfg.hxx | 112 + sw/source/uibase/inc/formatclipboard.hxx | 95 + sw/source/uibase/inc/frmdlg.hxx | 55 + sw/source/uibase/inc/frmmgr.hxx | 174 + sw/source/uibase/inc/frmpage.hxx | 324 + sw/source/uibase/inc/frmsh.hxx | 54 + sw/source/uibase/inc/globals.h | 31 + sw/source/uibase/inc/glosbib.hxx | 81 + sw/source/uibase/inc/glosdoc.hxx | 125 + sw/source/uibase/inc/gloshdl.hxx | 98 + sw/source/uibase/inc/gloslst.hxx | 82 + sw/source/uibase/inc/glossary.hxx | 123 + sw/source/uibase/inc/glshell.hxx | 85 + sw/source/uibase/inc/grfsh.hxx | 56 + sw/source/uibase/inc/hyp.hxx | 54 + sw/source/uibase/inc/idxmrk.hxx | 60 + sw/source/uibase/inc/imaildsplistener.hxx | 61 + sw/source/uibase/inc/initui.hxx | 52 + sw/source/uibase/inc/inpdlg.hxx | 68 + sw/source/uibase/inc/inputwin.hxx | 210 + sw/source/uibase/inc/insfnote.hxx | 85 + sw/source/uibase/inc/instable.hxx | 87 + sw/source/uibase/inc/javaedit.hxx | 79 + sw/source/uibase/inc/label.hxx | 84 + sw/source/uibase/inc/labelcfg.hxx | 61 + sw/source/uibase/inc/labimg.hxx | 125 + sw/source/uibase/inc/labimp.hxx | 36 + sw/source/uibase/inc/labrec.hxx | 57 + sw/source/uibase/inc/langhelper.hxx | 64 + sw/source/uibase/inc/linenum.hxx | 61 + sw/source/uibase/inc/listsh.hxx | 42 + sw/source/uibase/inc/macassgn.hxx | 48 + sw/source/uibase/inc/mailconfigpage.hxx | 69 + sw/source/uibase/inc/maildispatcher.hxx | 159 + sw/source/uibase/inc/mailmergehelper.hxx | 284 + sw/source/uibase/inc/mailmergewizard.hxx | 87 + sw/source/uibase/inc/mailmrge.hxx | 167 + sw/source/uibase/inc/mediash.hxx | 46 + sw/source/uibase/inc/mergetbl.hxx | 39 + sw/source/uibase/inc/mmconfigitem.hxx | 253 + sw/source/uibase/inc/multmrk.hxx | 45 + sw/source/uibase/inc/navicfg.hxx | 104 + sw/source/uibase/inc/navicont.hxx | 55 + sw/source/uibase/inc/navipi.hxx | 177 + sw/source/uibase/inc/navmgr.hxx | 58 + sw/source/uibase/inc/navsh.hxx | 36 + sw/source/uibase/inc/num.hxx | 138 + sw/source/uibase/inc/numberingtypelistbox.hxx | 60 + sw/source/uibase/inc/numfmtlb.hxx | 145 + sw/source/uibase/inc/numpara.hxx | 85 + sw/source/uibase/inc/numprevw.hxx | 67 + sw/source/uibase/inc/olesh.hxx | 39 + sw/source/uibase/inc/olmenu.hxx | 139 + sw/source/uibase/inc/optcomp.hxx | 79 + sw/source/uibase/inc/optload.hxx | 198 + sw/source/uibase/inc/optpage.hxx | 384 ++ sw/source/uibase/inc/outline.hxx | 123 + sw/source/uibase/inc/pardlg.hxx | 28 + sw/source/uibase/inc/pattern.hxx | 33 + sw/source/uibase/inc/pgfnote.hxx | 69 + sw/source/uibase/inc/pggrid.hxx | 91 + sw/source/uibase/inc/prcntfld.hxx | 85 + sw/source/uibase/inc/pview.hxx | 302 + sw/source/uibase/inc/redlndlg.hxx | 165 + sw/source/uibase/inc/regionsw.hxx | 257 + sw/source/uibase/inc/rowht.hxx | 43 + sw/source/uibase/inc/scroll.hxx | 57 + sw/source/uibase/inc/selglos.hxx | 51 + sw/source/uibase/inc/sharedconnection.hxx | 30 + sw/source/uibase/inc/shdwcrsr.hxx | 53 + sw/source/uibase/inc/splittbl.hxx | 57 + sw/source/uibase/inc/srcedtw.hxx | 148 + sw/source/uibase/inc/srcview.hxx | 89 + sw/source/uibase/inc/srtdlg.hxx | 89 + sw/source/uibase/inc/swcont.hxx | 104 + sw/source/uibase/inc/swdtflvr.hxx | 247 + sw/source/uibase/inc/swmessdialog.hxx | 27 + sw/source/uibase/inc/swmodalredlineacceptdlg.hxx | 41 + sw/source/uibase/inc/swrenamexnameddlg.hxx | 64 + sw/source/uibase/inc/swruler.hxx | 118 + sw/source/uibase/inc/swtablerep.hxx | 84 + sw/source/uibase/inc/swuiccoll.hxx | 73 + sw/source/uibase/inc/swuicnttab.hxx | 441 ++ sw/source/uibase/inc/swuiidxmrk.hxx | 235 + sw/source/uibase/inc/swuipardlg.hxx | 46 + sw/source/uibase/inc/swwrtshitem.hxx | 42 + sw/source/uibase/inc/syncbtn.hxx | 49 + sw/source/uibase/inc/tabledlg.hxx | 39 + sw/source/uibase/inc/tablemgr.hxx | 76 + sw/source/uibase/inc/tabsh.hxx | 55 + sw/source/uibase/inc/tautofmt.hxx | 89 + sw/source/uibase/inc/tblnumfm.hxx | 35 + sw/source/uibase/inc/textsh.hxx | 91 + sw/source/uibase/inc/titlepage.hxx | 62 + sw/source/uibase/inc/tmpdlg.hxx | 55 + sw/source/uibase/inc/tmplctrl.hxx | 44 + sw/source/uibase/inc/toxmgr.hxx | 271 + sw/source/uibase/inc/uiborder.hxx | 40 + sw/source/uibase/inc/uiitems.hxx | 108 + sw/source/uibase/inc/uinums.hxx | 119 + sw/source/uibase/inc/uiobject.hxx | 65 + sw/source/uibase/inc/uitool.hxx | 113 + sw/source/uibase/inc/uivwimp.hxx | 169 + sw/source/uibase/inc/unoatxt.hxx | 271 + sw/source/uibase/inc/unodispatch.hxx | 127 + sw/source/uibase/inc/unomailmerge.hxx | 170 + sw/source/uibase/inc/unomod.hxx | 138 + sw/source/uibase/inc/unotools.hxx | 84 + sw/source/uibase/inc/unotxvw.hxx | 247 + sw/source/uibase/inc/usrpref.hxx | 273 + sw/source/uibase/inc/viewlayoutctrl.hxx | 47 + sw/source/uibase/inc/watermarkdialog.hxx | 40 + sw/source/uibase/inc/wformsh.hxx | 41 + sw/source/uibase/inc/wfrmsh.hxx | 41 + sw/source/uibase/inc/wgrfsh.hxx | 39 + sw/source/uibase/inc/wlistsh.hxx | 41 + sw/source/uibase/inc/wolesh.hxx | 40 + sw/source/uibase/inc/wordcountctrl.hxx | 37 + sw/source/uibase/inc/wordcountdialog.hxx | 76 + sw/source/uibase/inc/workctrl.hxx | 94 + sw/source/uibase/inc/wrap.hxx | 97 + sw/source/uibase/inc/wrtsh.hxx | 652 ++ sw/source/uibase/inc/wtabsh.hxx | 40 + sw/source/uibase/inc/wtextsh.hxx | 41 + sw/source/uibase/inc/wview.hxx | 45 + sw/source/uibase/inc/zoomctrl.hxx | 43 + sw/source/uibase/index/idxmrk.cxx | 73 + sw/source/uibase/index/toxmgr.cxx | 497 ++ sw/source/uibase/lingu/hhcwrp.cxx | 693 +++ sw/source/uibase/lingu/hyp.cxx | 124 + sw/source/uibase/lingu/olmenu.cxx | 885 +++ sw/source/uibase/lingu/sdrhhcwrap.cxx | 164 + sw/source/uibase/lingu/sdrhhcwrap.hxx | 56 + sw/source/uibase/misc/glosdoc.cxx | 627 ++ sw/source/uibase/misc/glshell.cxx | 271 + sw/source/uibase/misc/numberingtypelistbox.cxx | 137 + sw/source/uibase/misc/redlndlg.cxx | 1261 ++++ sw/source/uibase/misc/swruler.cxx | 371 ++ sw/source/uibase/ribbar/conarc.cxx | 100 + sw/source/uibase/ribbar/concustomshape.cxx | 186 + sw/source/uibase/ribbar/conform.cxx | 108 + sw/source/uibase/ribbar/conpoly.cxx | 103 + sw/source/uibase/ribbar/conrect.cxx | 214 + sw/source/uibase/ribbar/drawbase.cxx | 550 ++ sw/source/uibase/ribbar/dselect.cxx | 44 + sw/source/uibase/ribbar/inputwin.cxx | 602 ++ sw/source/uibase/ribbar/workctrl.cxx | 1063 ++++ sw/source/uibase/shells/annotsh.cxx | 1812 ++++++ sw/source/uibase/shells/basesh.cxx | 3039 +++++++++ sw/source/uibase/shells/beziersh.cxx | 325 + sw/source/uibase/shells/drawdlg.cxx | 373 ++ sw/source/uibase/shells/drawsh.cxx | 603 ++ sw/source/uibase/shells/drformsh.cxx | 250 + sw/source/uibase/shells/drwbassh.cxx | 1042 ++++ sw/source/uibase/shells/drwtxtex.cxx | 1251 ++++ sw/source/uibase/shells/drwtxtsh.cxx | 846 +++ sw/source/uibase/shells/frmsh.cxx | 1458 +++++ sw/source/uibase/shells/grfsh.cxx | 1016 ++++ sw/source/uibase/shells/grfshex.cxx | 123 + sw/source/uibase/shells/langhelper.cxx | 588 ++ sw/source/uibase/shells/listsh.cxx | 273 + sw/source/uibase/shells/mediash.cxx | 164 + sw/source/uibase/shells/navsh.cxx | 95 + sw/source/uibase/shells/olesh.cxx | 47 + sw/source/uibase/shells/slotadd.cxx | 133 + sw/source/uibase/shells/tabsh.cxx | 1602 +++++ sw/source/uibase/shells/textdrw.cxx | 125 + sw/source/uibase/shells/textfld.cxx | 1096 ++++ sw/source/uibase/shells/textglos.cxx | 125 + sw/source/uibase/shells/textidx.cxx | 236 + sw/source/uibase/shells/textsh.cxx | 1049 ++++ sw/source/uibase/shells/textsh1.cxx | 2179 +++++++ sw/source/uibase/shells/textsh2.cxx | 259 + sw/source/uibase/shells/txtattr.cxx | 845 +++ sw/source/uibase/shells/txtcrsr.cxx | 459 ++ sw/source/uibase/shells/txtnum.cxx | 310 + sw/source/uibase/sidebar/PageColumnControl.cxx | 122 + sw/source/uibase/sidebar/PageColumnControl.hxx | 56 + sw/source/uibase/sidebar/PageColumnPopup.cxx | 76 + sw/source/uibase/sidebar/PageFooterPanel.cxx | 295 + sw/source/uibase/sidebar/PageFooterPanel.hxx | 110 + sw/source/uibase/sidebar/PageFormatPanel.cxx | 432 ++ sw/source/uibase/sidebar/PageFormatPanel.hxx | 112 + sw/source/uibase/sidebar/PageHeaderPanel.cxx | 296 + sw/source/uibase/sidebar/PageHeaderPanel.hxx | 110 + sw/source/uibase/sidebar/PageMarginControl.cxx | 586 ++ sw/source/uibase/sidebar/PageMarginControl.hxx | 109 + sw/source/uibase/sidebar/PageMarginPopup.cxx | 75 + sw/source/uibase/sidebar/PageMarginUtils.hxx | 192 + .../uibase/sidebar/PageOrientationControl.cxx | 194 + .../uibase/sidebar/PageOrientationControl.hxx | 60 + sw/source/uibase/sidebar/PageOrientationPopup.cxx | 76 + sw/source/uibase/sidebar/PageSizeControl.cxx | 238 + sw/source/uibase/sidebar/PageSizeControl.hxx | 62 + sw/source/uibase/sidebar/PageSizePopup.cxx | 76 + sw/source/uibase/sidebar/PageStylesPanel.cxx | 604 ++ sw/source/uibase/sidebar/PageStylesPanel.hxx | 123 + sw/source/uibase/sidebar/StylePresetsPanel.cxx | 217 + sw/source/uibase/sidebar/StylePresetsPanel.hxx | 71 + sw/source/uibase/sidebar/SwPanelFactory.cxx | 204 + sw/source/uibase/sidebar/TableEditPanel.cxx | 238 + sw/source/uibase/sidebar/TableEditPanel.hxx | 93 + sw/source/uibase/sidebar/ThemePanel.cxx | 509 ++ sw/source/uibase/sidebar/ThemePanel.hxx | 63 + sw/source/uibase/sidebar/WrapPropertyPanel.cxx | 189 + sw/source/uibase/sidebar/WrapPropertyPanel.hxx | 88 + sw/source/uibase/table/chartins.cxx | 228 + sw/source/uibase/table/swtablerep.cxx | 150 + sw/source/uibase/table/tablemgr.cxx | 352 ++ sw/source/uibase/table/tablepg.hxx | 183 + sw/source/uibase/uitest/uiobject.cxx | 172 + sw/source/uibase/uiview/formatclipboard.cxx | 593 ++ sw/source/uibase/uiview/pview.cxx | 1887 ++++++ sw/source/uibase/uiview/scroll.cxx | 119 + sw/source/uibase/uiview/srcview.cxx | 849 +++ sw/source/uibase/uiview/swcli.cxx | 167 + sw/source/uibase/uiview/uivwimp.cxx | 322 + sw/source/uibase/uiview/view.cxx | 1871 ++++++ sw/source/uibase/uiview/view0.cxx | 648 ++ sw/source/uibase/uiview/view1.cxx | 217 + sw/source/uibase/uiview/view2.cxx | 2573 ++++++++ sw/source/uibase/uiview/viewcoll.cxx | 77 + sw/source/uibase/uiview/viewdlg.cxx | 65 + sw/source/uibase/uiview/viewdlg2.cxx | 283 + sw/source/uibase/uiview/viewdraw.cxx | 749 +++ sw/source/uibase/uiview/viewfunc.hxx | 55 + sw/source/uibase/uiview/viewling.cxx | 837 +++ sw/source/uibase/uiview/viewmdi.cxx | 700 +++ sw/source/uibase/uiview/viewport.cxx | 1235 ++++ sw/source/uibase/uiview/viewprt.cxx | 350 ++ sw/source/uibase/uiview/viewsrch.cxx | 869 +++ sw/source/uibase/uiview/viewstat.cxx | 603 ++ sw/source/uibase/uiview/viewtab.cxx | 2532 ++++++++ sw/source/uibase/uno/SwXDocumentSettings.cxx | 1508 +++++ sw/source/uibase/uno/SwXDocumentSettings.hxx | 80 + sw/source/uibase/uno/SwXFilterOptions.cxx | 146 + sw/source/uibase/uno/dlelstnr.cxx | 133 + sw/source/uibase/uno/unoatxt.cxx | 1053 ++++ sw/source/uibase/uno/unodefaults.cxx | 52 + sw/source/uibase/uno/unodefaults.hxx | 38 + sw/source/uibase/uno/unodispatch.cxx | 393 ++ sw/source/uibase/uno/unodoc.cxx | 82 + sw/source/uibase/uno/unofreg.cxx | 89 + sw/source/uibase/uno/unomailmerge.cxx | 1174 ++++ sw/source/uibase/uno/unomod.cxx | 970 +++ sw/source/uibase/uno/unomodule.cxx | 150 + sw/source/uibase/uno/unomodule.hxx | 76 + sw/source/uibase/uno/unotxdoc.cxx | 4475 ++++++++++++++ sw/source/uibase/uno/unotxvw.cxx | 1756 ++++++ sw/source/uibase/utlui/attrdesc.cxx | 844 +++ sw/source/uibase/utlui/bookctrl.cxx | 141 + sw/source/uibase/utlui/condedit.cxx | 84 + sw/source/uibase/utlui/content.cxx | 4033 ++++++++++++ sw/source/uibase/utlui/glbltree.cxx | 1088 ++++ sw/source/uibase/utlui/gloslst.cxx | 441 ++ sw/source/uibase/utlui/gotodlg.cxx | 102 + sw/source/uibase/utlui/initui.cxx | 289 + sw/source/uibase/utlui/navicfg.cxx | 128 + sw/source/uibase/utlui/navipi.cxx | 1128 ++++ sw/source/uibase/utlui/numfmtlb.cxx | 473 ++ sw/source/uibase/utlui/prcntfld.cxx | 228 + sw/source/uibase/utlui/shdwcrsr.cxx | 119 + sw/source/uibase/utlui/tmplctrl.cxx | 142 + sw/source/uibase/utlui/uiitems.cxx | 275 + sw/source/uibase/utlui/uitool.cxx | 848 +++ sw/source/uibase/utlui/unotools.cxx | 510 ++ sw/source/uibase/utlui/viewlayoutctrl.cxx | 197 + sw/source/uibase/utlui/wordcountctrl.cxx | 39 + sw/source/uibase/utlui/zoomctrl.cxx | 65 + sw/source/uibase/web/wdocsh.cxx | 80 + sw/source/uibase/web/wformsh.cxx | 50 + sw/source/uibase/web/wfrmsh.cxx | 50 + sw/source/uibase/web/wgrfsh.cxx | 54 + sw/source/uibase/web/wlistsh.cxx | 49 + sw/source/uibase/web/wolesh.cxx | 48 + sw/source/uibase/web/wtabsh.cxx | 52 + sw/source/uibase/web/wtextsh.cxx | 56 + sw/source/uibase/web/wview.cxx | 292 + sw/source/uibase/wrtsh/delete.cxx | 631 ++ sw/source/uibase/wrtsh/move.cxx | 691 +++ sw/source/uibase/wrtsh/navmgr.cxx | 247 + sw/source/uibase/wrtsh/select.cxx | 993 +++ sw/source/uibase/wrtsh/wrtsh1.cxx | 1990 ++++++ sw/source/uibase/wrtsh/wrtsh2.cxx | 606 ++ sw/source/uibase/wrtsh/wrtsh3.cxx | 253 + sw/source/uibase/wrtsh/wrtsh4.cxx | 235 + sw/source/uibase/wrtsh/wrtundo.cxx | 150 + 442 files changed, 155928 insertions(+) create mode 100644 sw/source/uibase/app/appenv.cxx create mode 100644 sw/source/uibase/app/appenv.hxx create mode 100644 sw/source/uibase/app/apphdl.cxx create mode 100644 sw/source/uibase/app/applab.cxx create mode 100644 sw/source/uibase/app/appopt.cxx create mode 100644 sw/source/uibase/app/docsh.cxx create mode 100644 sw/source/uibase/app/docsh2.cxx create mode 100644 sw/source/uibase/app/docshdrw.cxx create mode 100644 sw/source/uibase/app/docshini.cxx create mode 100644 sw/source/uibase/app/docst.cxx create mode 100644 sw/source/uibase/app/docstyle.cxx create mode 100644 sw/source/uibase/app/mainwn.cxx create mode 100644 sw/source/uibase/app/swdll.cxx create mode 100644 sw/source/uibase/app/swdllimpl.hxx create mode 100644 sw/source/uibase/app/swmodul1.cxx create mode 100644 sw/source/uibase/app/swmodule.cxx create mode 100644 sw/source/uibase/app/swwait.cxx create mode 100644 sw/source/uibase/chrdlg/ccoll.cxx create mode 100644 sw/source/uibase/config/StoredChapterNumbering.cxx create mode 100644 sw/source/uibase/config/barcfg.cxx create mode 100644 sw/source/uibase/config/caption.cxx create mode 100644 sw/source/uibase/config/cfgitems.cxx create mode 100644 sw/source/uibase/config/dbconfig.cxx create mode 100644 sw/source/uibase/config/fontcfg.cxx create mode 100644 sw/source/uibase/config/modcfg.cxx create mode 100644 sw/source/uibase/config/prtopt.cxx create mode 100644 sw/source/uibase/config/uinums.cxx create mode 100644 sw/source/uibase/config/usrpref.cxx create mode 100644 sw/source/uibase/config/viewopt.cxx create mode 100644 sw/source/uibase/dbui/README create mode 100644 sw/source/uibase/dbui/dbmgr.cxx create mode 100644 sw/source/uibase/dbui/dbtree.cxx create mode 100644 sw/source/uibase/dbui/dbui.cxx create mode 100644 sw/source/uibase/dbui/maildispatcher.cxx create mode 100644 sw/source/uibase/dbui/mailmergehelper.cxx create mode 100644 sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx create mode 100644 sw/source/uibase/dbui/mmconfigitem.cxx create mode 100644 sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx create mode 100644 sw/source/uibase/dialog/regionsw.cxx create mode 100644 sw/source/uibase/dialog/swabstdlg.cxx create mode 100644 sw/source/uibase/dialog/swwrtshitem.cxx create mode 100644 sw/source/uibase/dialog/watermarkdialog.cxx create mode 100644 sw/source/uibase/dialog/wordcountwrapper.cxx create mode 100644 sw/source/uibase/dochdl/gloshdl.cxx create mode 100644 sw/source/uibase/dochdl/swdtflvr.cxx create mode 100644 sw/source/uibase/docvw/AnchorOverlayObject.cxx create mode 100644 sw/source/uibase/docvw/AnchorOverlayObject.hxx create mode 100644 sw/source/uibase/docvw/AnnotationMenuButton.cxx create mode 100644 sw/source/uibase/docvw/AnnotationMenuButton.hxx create mode 100644 sw/source/uibase/docvw/AnnotationWin.cxx create mode 100644 sw/source/uibase/docvw/AnnotationWin2.cxx create mode 100644 sw/source/uibase/docvw/DashedLine.cxx create mode 100644 sw/source/uibase/docvw/FrameControlsManager.cxx create mode 100644 sw/source/uibase/docvw/HeaderFooterWin.cxx create mode 100644 sw/source/uibase/docvw/OverlayRanges.cxx create mode 100644 sw/source/uibase/docvw/OverlayRanges.hxx create mode 100644 sw/source/uibase/docvw/PageBreakWin.cxx create mode 100644 sw/source/uibase/docvw/PostItMgr.cxx create mode 100644 sw/source/uibase/docvw/ShadowOverlayObject.cxx create mode 100644 sw/source/uibase/docvw/ShadowOverlayObject.hxx create mode 100644 sw/source/uibase/docvw/SidebarScrollBar.cxx create mode 100644 sw/source/uibase/docvw/SidebarScrollBar.hxx create mode 100644 sw/source/uibase/docvw/SidebarTxtControl.cxx create mode 100644 sw/source/uibase/docvw/SidebarTxtControl.hxx create mode 100644 sw/source/uibase/docvw/SidebarTxtControlAcc.cxx create mode 100644 sw/source/uibase/docvw/SidebarTxtControlAcc.hxx create mode 100644 sw/source/uibase/docvw/SidebarWinAcc.cxx create mode 100644 sw/source/uibase/docvw/SidebarWinAcc.hxx create mode 100644 sw/source/uibase/docvw/UnfloatTableButton.cxx create mode 100644 sw/source/uibase/docvw/edtdd.cxx create mode 100644 sw/source/uibase/docvw/edtwin.cxx create mode 100644 sw/source/uibase/docvw/edtwin2.cxx create mode 100644 sw/source/uibase/docvw/edtwin3.cxx create mode 100644 sw/source/uibase/docvw/frmsidebarwincontainer.cxx create mode 100644 sw/source/uibase/docvw/frmsidebarwincontainer.hxx create mode 100644 sw/source/uibase/docvw/romenu.cxx create mode 100644 sw/source/uibase/docvw/romenu.hxx create mode 100644 sw/source/uibase/docvw/srcedtw.cxx create mode 100644 sw/source/uibase/envelp/envimg.cxx create mode 100644 sw/source/uibase/envelp/labelcfg.cxx create mode 100644 sw/source/uibase/envelp/labimg.cxx create mode 100644 sw/source/uibase/envelp/syncbtn.cxx create mode 100644 sw/source/uibase/fldui/fldmgr.cxx create mode 100644 sw/source/uibase/fldui/fldwrap.cxx create mode 100644 sw/source/uibase/fldui/xfldui.cxx create mode 100644 sw/source/uibase/frmdlg/colex.cxx create mode 100644 sw/source/uibase/frmdlg/colmgr.cxx create mode 100644 sw/source/uibase/frmdlg/frmmgr.cxx create mode 100644 sw/source/uibase/globdoc/globdoc.cxx create mode 100644 sw/source/uibase/inc/DashedLine.hxx create mode 100644 sw/source/uibase/inc/DateFormFieldDialog.hxx create mode 100644 sw/source/uibase/inc/DropDownFieldDialog.hxx create mode 100644 sw/source/uibase/inc/DropDownFormFieldDialog.hxx create mode 100644 sw/source/uibase/inc/FrameControl.hxx create mode 100644 sw/source/uibase/inc/FrameControlsManager.hxx create mode 100644 sw/source/uibase/inc/HeaderFooterWin.hxx create mode 100644 sw/source/uibase/inc/PageBreakWin.hxx create mode 100644 sw/source/uibase/inc/SidebarWindowsConsts.hxx create mode 100644 sw/source/uibase/inc/SwSpellDialogChildWindow.hxx create mode 100644 sw/source/uibase/inc/SwXFilterOptions.hxx create mode 100644 sw/source/uibase/inc/UnfloatTableButton.hxx create mode 100644 sw/source/uibase/inc/abstract.hxx create mode 100644 sw/source/uibase/inc/addrdlg.hxx create mode 100644 sw/source/uibase/inc/annotsh.hxx create mode 100644 sw/source/uibase/inc/ascfldlg.hxx create mode 100644 sw/source/uibase/inc/autoformatpreview.hxx create mode 100644 sw/source/uibase/inc/barcfg.hxx create mode 100644 sw/source/uibase/inc/basesh.hxx create mode 100644 sw/source/uibase/inc/beziersh.hxx create mode 100644 sw/source/uibase/inc/bmpwin.hxx create mode 100644 sw/source/uibase/inc/bookctrl.hxx create mode 100644 sw/source/uibase/inc/bookmark.hxx create mode 100644 sw/source/uibase/inc/break.hxx create mode 100644 sw/source/uibase/inc/caption.hxx create mode 100644 sw/source/uibase/inc/cfgitems.hxx create mode 100644 sw/source/uibase/inc/changedb.hxx create mode 100644 sw/source/uibase/inc/chartins.hxx create mode 100644 sw/source/uibase/inc/chldwrap.hxx create mode 100644 sw/source/uibase/inc/chrdlg.hxx create mode 100644 sw/source/uibase/inc/chrdlgmodes.hxx create mode 100644 sw/source/uibase/inc/cnttab.hxx create mode 100644 sw/source/uibase/inc/colex.hxx create mode 100644 sw/source/uibase/inc/colmgr.hxx create mode 100644 sw/source/uibase/inc/column.hxx create mode 100644 sw/source/uibase/inc/conarc.hxx create mode 100644 sw/source/uibase/inc/concustomshape.hxx create mode 100644 sw/source/uibase/inc/condedit.hxx create mode 100644 sw/source/uibase/inc/conform.hxx create mode 100644 sw/source/uibase/inc/conpoly.hxx create mode 100644 sw/source/uibase/inc/conrect.hxx create mode 100644 sw/source/uibase/inc/content.hxx create mode 100644 sw/source/uibase/inc/conttree.hxx create mode 100644 sw/source/uibase/inc/convert.hxx create mode 100644 sw/source/uibase/inc/cption.hxx create mode 100644 sw/source/uibase/inc/dbconfig.hxx create mode 100644 sw/source/uibase/inc/dbinsdlg.hxx create mode 100644 sw/source/uibase/inc/dbtree.hxx create mode 100644 sw/source/uibase/inc/dbui.hxx create mode 100644 sw/source/uibase/inc/docfnote.hxx create mode 100644 sw/source/uibase/inc/docstdlg.hxx create mode 100644 sw/source/uibase/inc/drawbase.hxx create mode 100644 sw/source/uibase/inc/drawsh.hxx create mode 100644 sw/source/uibase/inc/drformsh.hxx create mode 100644 sw/source/uibase/inc/drpcps.hxx create mode 100644 sw/source/uibase/inc/drwbassh.hxx create mode 100644 sw/source/uibase/inc/drwtxtsh.hxx create mode 100644 sw/source/uibase/inc/dselect.hxx create mode 100644 sw/source/uibase/inc/edtdd.hxx create mode 100644 sw/source/uibase/inc/edtwin.hxx create mode 100644 sw/source/uibase/inc/envimg.hxx create mode 100644 sw/source/uibase/inc/envlop.hxx create mode 100644 sw/source/uibase/inc/fldedt.hxx create mode 100644 sw/source/uibase/inc/fldmgr.hxx create mode 100644 sw/source/uibase/inc/fldtdlg.hxx create mode 100644 sw/source/uibase/inc/fldwrap.hxx create mode 100644 sw/source/uibase/inc/fontcfg.hxx create mode 100644 sw/source/uibase/inc/formatclipboard.hxx create mode 100644 sw/source/uibase/inc/frmdlg.hxx create mode 100644 sw/source/uibase/inc/frmmgr.hxx create mode 100644 sw/source/uibase/inc/frmpage.hxx create mode 100644 sw/source/uibase/inc/frmsh.hxx create mode 100644 sw/source/uibase/inc/globals.h create mode 100644 sw/source/uibase/inc/glosbib.hxx create mode 100644 sw/source/uibase/inc/glosdoc.hxx create mode 100644 sw/source/uibase/inc/gloshdl.hxx create mode 100644 sw/source/uibase/inc/gloslst.hxx create mode 100644 sw/source/uibase/inc/glossary.hxx create mode 100644 sw/source/uibase/inc/glshell.hxx create mode 100644 sw/source/uibase/inc/grfsh.hxx create mode 100644 sw/source/uibase/inc/hyp.hxx create mode 100644 sw/source/uibase/inc/idxmrk.hxx create mode 100644 sw/source/uibase/inc/imaildsplistener.hxx create mode 100644 sw/source/uibase/inc/initui.hxx create mode 100644 sw/source/uibase/inc/inpdlg.hxx create mode 100644 sw/source/uibase/inc/inputwin.hxx create mode 100644 sw/source/uibase/inc/insfnote.hxx create mode 100644 sw/source/uibase/inc/instable.hxx create mode 100644 sw/source/uibase/inc/javaedit.hxx create mode 100644 sw/source/uibase/inc/label.hxx create mode 100644 sw/source/uibase/inc/labelcfg.hxx create mode 100644 sw/source/uibase/inc/labimg.hxx create mode 100644 sw/source/uibase/inc/labimp.hxx create mode 100644 sw/source/uibase/inc/labrec.hxx create mode 100644 sw/source/uibase/inc/langhelper.hxx create mode 100644 sw/source/uibase/inc/linenum.hxx create mode 100644 sw/source/uibase/inc/listsh.hxx create mode 100644 sw/source/uibase/inc/macassgn.hxx create mode 100644 sw/source/uibase/inc/mailconfigpage.hxx create mode 100644 sw/source/uibase/inc/maildispatcher.hxx create mode 100644 sw/source/uibase/inc/mailmergehelper.hxx create mode 100644 sw/source/uibase/inc/mailmergewizard.hxx create mode 100644 sw/source/uibase/inc/mailmrge.hxx create mode 100644 sw/source/uibase/inc/mediash.hxx create mode 100644 sw/source/uibase/inc/mergetbl.hxx create mode 100644 sw/source/uibase/inc/mmconfigitem.hxx create mode 100644 sw/source/uibase/inc/multmrk.hxx create mode 100644 sw/source/uibase/inc/navicfg.hxx create mode 100644 sw/source/uibase/inc/navicont.hxx create mode 100644 sw/source/uibase/inc/navipi.hxx create mode 100644 sw/source/uibase/inc/navmgr.hxx create mode 100644 sw/source/uibase/inc/navsh.hxx create mode 100644 sw/source/uibase/inc/num.hxx create mode 100644 sw/source/uibase/inc/numberingtypelistbox.hxx create mode 100644 sw/source/uibase/inc/numfmtlb.hxx create mode 100644 sw/source/uibase/inc/numpara.hxx create mode 100644 sw/source/uibase/inc/numprevw.hxx create mode 100644 sw/source/uibase/inc/olesh.hxx create mode 100644 sw/source/uibase/inc/olmenu.hxx create mode 100644 sw/source/uibase/inc/optcomp.hxx create mode 100644 sw/source/uibase/inc/optload.hxx create mode 100644 sw/source/uibase/inc/optpage.hxx create mode 100644 sw/source/uibase/inc/outline.hxx create mode 100644 sw/source/uibase/inc/pardlg.hxx create mode 100644 sw/source/uibase/inc/pattern.hxx create mode 100644 sw/source/uibase/inc/pgfnote.hxx create mode 100644 sw/source/uibase/inc/pggrid.hxx create mode 100644 sw/source/uibase/inc/prcntfld.hxx create mode 100644 sw/source/uibase/inc/pview.hxx create mode 100644 sw/source/uibase/inc/redlndlg.hxx create mode 100644 sw/source/uibase/inc/regionsw.hxx create mode 100644 sw/source/uibase/inc/rowht.hxx create mode 100644 sw/source/uibase/inc/scroll.hxx create mode 100644 sw/source/uibase/inc/selglos.hxx create mode 100644 sw/source/uibase/inc/sharedconnection.hxx create mode 100644 sw/source/uibase/inc/shdwcrsr.hxx create mode 100644 sw/source/uibase/inc/splittbl.hxx create mode 100644 sw/source/uibase/inc/srcedtw.hxx create mode 100644 sw/source/uibase/inc/srcview.hxx create mode 100644 sw/source/uibase/inc/srtdlg.hxx create mode 100644 sw/source/uibase/inc/swcont.hxx create mode 100644 sw/source/uibase/inc/swdtflvr.hxx create mode 100644 sw/source/uibase/inc/swmessdialog.hxx create mode 100644 sw/source/uibase/inc/swmodalredlineacceptdlg.hxx create mode 100644 sw/source/uibase/inc/swrenamexnameddlg.hxx create mode 100644 sw/source/uibase/inc/swruler.hxx create mode 100644 sw/source/uibase/inc/swtablerep.hxx create mode 100644 sw/source/uibase/inc/swuiccoll.hxx create mode 100644 sw/source/uibase/inc/swuicnttab.hxx create mode 100644 sw/source/uibase/inc/swuiidxmrk.hxx create mode 100644 sw/source/uibase/inc/swuipardlg.hxx create mode 100644 sw/source/uibase/inc/swwrtshitem.hxx create mode 100644 sw/source/uibase/inc/syncbtn.hxx create mode 100644 sw/source/uibase/inc/tabledlg.hxx create mode 100644 sw/source/uibase/inc/tablemgr.hxx create mode 100644 sw/source/uibase/inc/tabsh.hxx create mode 100644 sw/source/uibase/inc/tautofmt.hxx create mode 100644 sw/source/uibase/inc/tblnumfm.hxx create mode 100644 sw/source/uibase/inc/textsh.hxx create mode 100644 sw/source/uibase/inc/titlepage.hxx create mode 100644 sw/source/uibase/inc/tmpdlg.hxx create mode 100644 sw/source/uibase/inc/tmplctrl.hxx create mode 100644 sw/source/uibase/inc/toxmgr.hxx create mode 100644 sw/source/uibase/inc/uiborder.hxx create mode 100644 sw/source/uibase/inc/uiitems.hxx create mode 100644 sw/source/uibase/inc/uinums.hxx create mode 100644 sw/source/uibase/inc/uiobject.hxx create mode 100644 sw/source/uibase/inc/uitool.hxx create mode 100644 sw/source/uibase/inc/uivwimp.hxx create mode 100644 sw/source/uibase/inc/unoatxt.hxx create mode 100644 sw/source/uibase/inc/unodispatch.hxx create mode 100644 sw/source/uibase/inc/unomailmerge.hxx create mode 100644 sw/source/uibase/inc/unomod.hxx create mode 100644 sw/source/uibase/inc/unotools.hxx create mode 100644 sw/source/uibase/inc/unotxvw.hxx create mode 100644 sw/source/uibase/inc/usrpref.hxx create mode 100644 sw/source/uibase/inc/viewlayoutctrl.hxx create mode 100644 sw/source/uibase/inc/watermarkdialog.hxx create mode 100644 sw/source/uibase/inc/wformsh.hxx create mode 100644 sw/source/uibase/inc/wfrmsh.hxx create mode 100644 sw/source/uibase/inc/wgrfsh.hxx create mode 100644 sw/source/uibase/inc/wlistsh.hxx create mode 100644 sw/source/uibase/inc/wolesh.hxx create mode 100644 sw/source/uibase/inc/wordcountctrl.hxx create mode 100644 sw/source/uibase/inc/wordcountdialog.hxx create mode 100644 sw/source/uibase/inc/workctrl.hxx create mode 100644 sw/source/uibase/inc/wrap.hxx create mode 100644 sw/source/uibase/inc/wrtsh.hxx create mode 100644 sw/source/uibase/inc/wtabsh.hxx create mode 100644 sw/source/uibase/inc/wtextsh.hxx create mode 100644 sw/source/uibase/inc/wview.hxx create mode 100644 sw/source/uibase/inc/zoomctrl.hxx create mode 100644 sw/source/uibase/index/idxmrk.cxx create mode 100644 sw/source/uibase/index/toxmgr.cxx create mode 100644 sw/source/uibase/lingu/hhcwrp.cxx create mode 100644 sw/source/uibase/lingu/hyp.cxx create mode 100644 sw/source/uibase/lingu/olmenu.cxx create mode 100644 sw/source/uibase/lingu/sdrhhcwrap.cxx create mode 100644 sw/source/uibase/lingu/sdrhhcwrap.hxx create mode 100644 sw/source/uibase/misc/glosdoc.cxx create mode 100644 sw/source/uibase/misc/glshell.cxx create mode 100644 sw/source/uibase/misc/numberingtypelistbox.cxx create mode 100644 sw/source/uibase/misc/redlndlg.cxx create mode 100644 sw/source/uibase/misc/swruler.cxx create mode 100644 sw/source/uibase/ribbar/conarc.cxx create mode 100644 sw/source/uibase/ribbar/concustomshape.cxx create mode 100644 sw/source/uibase/ribbar/conform.cxx create mode 100644 sw/source/uibase/ribbar/conpoly.cxx create mode 100644 sw/source/uibase/ribbar/conrect.cxx create mode 100644 sw/source/uibase/ribbar/drawbase.cxx create mode 100644 sw/source/uibase/ribbar/dselect.cxx create mode 100644 sw/source/uibase/ribbar/inputwin.cxx create mode 100644 sw/source/uibase/ribbar/workctrl.cxx create mode 100644 sw/source/uibase/shells/annotsh.cxx create mode 100644 sw/source/uibase/shells/basesh.cxx create mode 100644 sw/source/uibase/shells/beziersh.cxx create mode 100644 sw/source/uibase/shells/drawdlg.cxx create mode 100644 sw/source/uibase/shells/drawsh.cxx create mode 100644 sw/source/uibase/shells/drformsh.cxx create mode 100644 sw/source/uibase/shells/drwbassh.cxx create mode 100644 sw/source/uibase/shells/drwtxtex.cxx create mode 100644 sw/source/uibase/shells/drwtxtsh.cxx create mode 100644 sw/source/uibase/shells/frmsh.cxx create mode 100644 sw/source/uibase/shells/grfsh.cxx create mode 100644 sw/source/uibase/shells/grfshex.cxx create mode 100644 sw/source/uibase/shells/langhelper.cxx create mode 100644 sw/source/uibase/shells/listsh.cxx create mode 100644 sw/source/uibase/shells/mediash.cxx create mode 100644 sw/source/uibase/shells/navsh.cxx create mode 100644 sw/source/uibase/shells/olesh.cxx create mode 100644 sw/source/uibase/shells/slotadd.cxx create mode 100644 sw/source/uibase/shells/tabsh.cxx create mode 100644 sw/source/uibase/shells/textdrw.cxx create mode 100644 sw/source/uibase/shells/textfld.cxx create mode 100644 sw/source/uibase/shells/textglos.cxx create mode 100644 sw/source/uibase/shells/textidx.cxx create mode 100644 sw/source/uibase/shells/textsh.cxx create mode 100644 sw/source/uibase/shells/textsh1.cxx create mode 100644 sw/source/uibase/shells/textsh2.cxx create mode 100644 sw/source/uibase/shells/txtattr.cxx create mode 100644 sw/source/uibase/shells/txtcrsr.cxx create mode 100644 sw/source/uibase/shells/txtnum.cxx create mode 100644 sw/source/uibase/sidebar/PageColumnControl.cxx create mode 100644 sw/source/uibase/sidebar/PageColumnControl.hxx create mode 100644 sw/source/uibase/sidebar/PageColumnPopup.cxx create mode 100644 sw/source/uibase/sidebar/PageFooterPanel.cxx create mode 100644 sw/source/uibase/sidebar/PageFooterPanel.hxx create mode 100644 sw/source/uibase/sidebar/PageFormatPanel.cxx create mode 100644 sw/source/uibase/sidebar/PageFormatPanel.hxx create mode 100644 sw/source/uibase/sidebar/PageHeaderPanel.cxx create mode 100644 sw/source/uibase/sidebar/PageHeaderPanel.hxx create mode 100644 sw/source/uibase/sidebar/PageMarginControl.cxx create mode 100644 sw/source/uibase/sidebar/PageMarginControl.hxx create mode 100644 sw/source/uibase/sidebar/PageMarginPopup.cxx create mode 100644 sw/source/uibase/sidebar/PageMarginUtils.hxx create mode 100644 sw/source/uibase/sidebar/PageOrientationControl.cxx create mode 100644 sw/source/uibase/sidebar/PageOrientationControl.hxx create mode 100644 sw/source/uibase/sidebar/PageOrientationPopup.cxx create mode 100644 sw/source/uibase/sidebar/PageSizeControl.cxx create mode 100644 sw/source/uibase/sidebar/PageSizeControl.hxx create mode 100644 sw/source/uibase/sidebar/PageSizePopup.cxx create mode 100644 sw/source/uibase/sidebar/PageStylesPanel.cxx create mode 100644 sw/source/uibase/sidebar/PageStylesPanel.hxx create mode 100644 sw/source/uibase/sidebar/StylePresetsPanel.cxx create mode 100644 sw/source/uibase/sidebar/StylePresetsPanel.hxx create mode 100644 sw/source/uibase/sidebar/SwPanelFactory.cxx create mode 100644 sw/source/uibase/sidebar/TableEditPanel.cxx create mode 100644 sw/source/uibase/sidebar/TableEditPanel.hxx create mode 100644 sw/source/uibase/sidebar/ThemePanel.cxx create mode 100644 sw/source/uibase/sidebar/ThemePanel.hxx create mode 100644 sw/source/uibase/sidebar/WrapPropertyPanel.cxx create mode 100644 sw/source/uibase/sidebar/WrapPropertyPanel.hxx create mode 100644 sw/source/uibase/table/chartins.cxx create mode 100644 sw/source/uibase/table/swtablerep.cxx create mode 100644 sw/source/uibase/table/tablemgr.cxx create mode 100644 sw/source/uibase/table/tablepg.hxx create mode 100644 sw/source/uibase/uitest/uiobject.cxx create mode 100644 sw/source/uibase/uiview/formatclipboard.cxx create mode 100644 sw/source/uibase/uiview/pview.cxx create mode 100644 sw/source/uibase/uiview/scroll.cxx create mode 100644 sw/source/uibase/uiview/srcview.cxx create mode 100644 sw/source/uibase/uiview/swcli.cxx create mode 100644 sw/source/uibase/uiview/uivwimp.cxx create mode 100644 sw/source/uibase/uiview/view.cxx create mode 100644 sw/source/uibase/uiview/view0.cxx create mode 100644 sw/source/uibase/uiview/view1.cxx create mode 100644 sw/source/uibase/uiview/view2.cxx create mode 100644 sw/source/uibase/uiview/viewcoll.cxx create mode 100644 sw/source/uibase/uiview/viewdlg.cxx create mode 100644 sw/source/uibase/uiview/viewdlg2.cxx create mode 100644 sw/source/uibase/uiview/viewdraw.cxx create mode 100644 sw/source/uibase/uiview/viewfunc.hxx create mode 100644 sw/source/uibase/uiview/viewling.cxx create mode 100644 sw/source/uibase/uiview/viewmdi.cxx create mode 100644 sw/source/uibase/uiview/viewport.cxx create mode 100644 sw/source/uibase/uiview/viewprt.cxx create mode 100644 sw/source/uibase/uiview/viewsrch.cxx create mode 100644 sw/source/uibase/uiview/viewstat.cxx create mode 100644 sw/source/uibase/uiview/viewtab.cxx create mode 100644 sw/source/uibase/uno/SwXDocumentSettings.cxx create mode 100644 sw/source/uibase/uno/SwXDocumentSettings.hxx create mode 100644 sw/source/uibase/uno/SwXFilterOptions.cxx create mode 100644 sw/source/uibase/uno/dlelstnr.cxx create mode 100644 sw/source/uibase/uno/unoatxt.cxx create mode 100644 sw/source/uibase/uno/unodefaults.cxx create mode 100644 sw/source/uibase/uno/unodefaults.hxx create mode 100644 sw/source/uibase/uno/unodispatch.cxx create mode 100644 sw/source/uibase/uno/unodoc.cxx create mode 100644 sw/source/uibase/uno/unofreg.cxx create mode 100644 sw/source/uibase/uno/unomailmerge.cxx create mode 100644 sw/source/uibase/uno/unomod.cxx create mode 100644 sw/source/uibase/uno/unomodule.cxx create mode 100644 sw/source/uibase/uno/unomodule.hxx create mode 100644 sw/source/uibase/uno/unotxdoc.cxx create mode 100644 sw/source/uibase/uno/unotxvw.cxx create mode 100644 sw/source/uibase/utlui/attrdesc.cxx create mode 100644 sw/source/uibase/utlui/bookctrl.cxx create mode 100644 sw/source/uibase/utlui/condedit.cxx create mode 100644 sw/source/uibase/utlui/content.cxx create mode 100644 sw/source/uibase/utlui/glbltree.cxx create mode 100644 sw/source/uibase/utlui/gloslst.cxx create mode 100644 sw/source/uibase/utlui/gotodlg.cxx create mode 100644 sw/source/uibase/utlui/initui.cxx create mode 100644 sw/source/uibase/utlui/navicfg.cxx create mode 100644 sw/source/uibase/utlui/navipi.cxx create mode 100644 sw/source/uibase/utlui/numfmtlb.cxx create mode 100644 sw/source/uibase/utlui/prcntfld.cxx create mode 100644 sw/source/uibase/utlui/shdwcrsr.cxx create mode 100644 sw/source/uibase/utlui/tmplctrl.cxx create mode 100644 sw/source/uibase/utlui/uiitems.cxx create mode 100644 sw/source/uibase/utlui/uitool.cxx create mode 100644 sw/source/uibase/utlui/unotools.cxx create mode 100644 sw/source/uibase/utlui/viewlayoutctrl.cxx create mode 100644 sw/source/uibase/utlui/wordcountctrl.cxx create mode 100644 sw/source/uibase/utlui/zoomctrl.cxx create mode 100644 sw/source/uibase/web/wdocsh.cxx create mode 100644 sw/source/uibase/web/wformsh.cxx create mode 100644 sw/source/uibase/web/wfrmsh.cxx create mode 100644 sw/source/uibase/web/wgrfsh.cxx create mode 100644 sw/source/uibase/web/wlistsh.cxx create mode 100644 sw/source/uibase/web/wolesh.cxx create mode 100644 sw/source/uibase/web/wtabsh.cxx create mode 100644 sw/source/uibase/web/wtextsh.cxx create mode 100644 sw/source/uibase/web/wview.cxx create mode 100644 sw/source/uibase/wrtsh/delete.cxx create mode 100644 sw/source/uibase/wrtsh/move.cxx create mode 100644 sw/source/uibase/wrtsh/navmgr.cxx create mode 100644 sw/source/uibase/wrtsh/select.cxx create mode 100644 sw/source/uibase/wrtsh/wrtsh1.cxx create mode 100644 sw/source/uibase/wrtsh/wrtsh2.cxx create mode 100644 sw/source/uibase/wrtsh/wrtsh3.cxx create mode 100644 sw/source/uibase/wrtsh/wrtsh4.cxx create mode 100644 sw/source/uibase/wrtsh/wrtundo.cxx (limited to 'sw/source/uibase') diff --git a/sw/source/uibase/app/appenv.cxx b/sw/source/uibase/app/appenv.cxx new file mode 100644 index 000000000..71b042b28 --- /dev/null +++ b/sw/source/uibase/app/appenv.cxx @@ -0,0 +1,493 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#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( 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( pFrame->GetViewShell()); + pNewView->AttrChangedNotify(nullptr); // so that SelectShell is being called + pSh = pNewView->GetWrtShellPtr(); + + 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_JAKETADRESS); + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS); + } + + // Read SwEnvItem from config + SwEnvCfgItem aEnvCfg; + + // Check if there's already an envelope. + bool bEnvChange = false; + + SfxItemSet aSet(GetPool(), svl::Items{}); + aSet.Put(aEnvCfg.GetItem()); + + SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess().getPrinter( true ); + if(pOldSh ) + { + const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc()); + OUString sJacket; + SwStyleNameMapper::FillUIName( RES_POOLPAGE_JAKET, sJacket ); + bEnvChange = rCurPageDesc.GetName() == sJacket; + + 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 pDlg; + short nMode = ENV_INSERT; + + const SwEnvItem* pItem = rReq.GetArg(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(FN_PARAM_1); + if ( pBoolItem && pBoolItem->GetValue() ) + nMode = ENV_NEWDOC; + } + + if (nMode == ENV_NEWDOC || nMode == ENV_INSERT) + { + SwWait aWait( static_cast(*xDocSh), true ); + + // Read dialog and save item to config + const SwEnvItem& rItem = pItem ? *pItem : static_cast( 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(pSh->getIDocumentDeviceAccess().getPrinter(true)->GetPaperBin())); + pOldSh->GetPageDescFromPool(RES_POOLPAGE_JAKET)->GetMaster().SetFormatAttr(aItem); + } + + SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh; + const SwPageDesc* pFollow = nullptr; + SwTextFormatColl *pSend = pTmp->GetTextCollFromPool( RES_POOLCOLL_SENDADRESS ), + *pAddr = pTmp->GetTextCollFromPool( RES_POOLCOLL_JAKETADRESS); + 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( CRSR_SKIP_CHARS, false, 1, false ); + SfxItemSet aBreakSet( pSh->GetAttrPool(), svl::Items{} ); + 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_JAKETADRESS); + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SENDADRESS); + } + } + + SET_CURR_SHELL(pSh); + pSh->SetNewDoc(); // Avoid performance problems + + // Remember Flys of this site + std::vector aFlyArr; + if( ENV_NEWDOC != nMode && !bEnvChange ) + pSh->GetPageObjs( aFlyArr ); + + // Get page description + SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_JAKET); + 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 ); + + long lLeft = rItem.m_nShiftRight, + lUpper = rItem.m_nShiftDown; + + sal_uInt16 nPageW = static_cast(std::max(rItem.m_nWidth, rItem.m_nHeight)), + nPageH = static_cast(std::min(rItem.m_nWidth, rItem.m_nHeight)); + + switch (rItem.m_eAlign) + { + case ENV_HOR_LEFT: break; + case ENV_HOR_CNTR: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW)) / 2; + break; + case ENV_HOR_RGHT: lLeft += std::max(0L, long(aPaperSize.Width() - nPageW)); + break; + case ENV_VER_LEFT: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH)); + break; + case ENV_VER_CNTR: lUpper += std::max(0L, long(aPaperSize.Width() - nPageH)) / 2; + break; + case ENV_VER_RGHT: break; + } + SvxLRSpaceItem aLRMargin( RES_LR_SPACE ); + SvxULSpaceItem aULMargin( RES_UL_SPACE ); + aLRMargin.SetLeft (static_cast(lLeft) ); + aULMargin.SetUpper(static_cast(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 000000000..64fcd4a81 --- /dev/null +++ b/sw/source/uibase/app/appenv.hxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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_APP_APPENV_HXX +#define INCLUDED_SW_SOURCE_UIBASE_APP_APPENV_HXX + +#include + +class SwWrtShell; +class SwFieldMgr; + +OUString InsertLabEnvText( SwWrtShell& , SwFieldMgr& , const OUString& ); + + +#endif + +/* 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 000000000..d92879eb3 --- /dev/null +++ b/sw/source/uibase/app/apphdl.cxx @@ -0,0 +1,1077 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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 +#include + +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( 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( 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: + { + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + 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: + { + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + xConfigItem = pView->EnsureMailMergeConfigItem(); + + // #i51949# hide e-Mail option if e-Mail is not supported + // #i63267# printing might be disabled + if (!xConfigItem || + !xConfigItem->GetConnection().is() || + xConfigItem->GetConnection()->isClosed() || + !xConfigItem->GetResultSet().is() || + xConfigItem->GetCurrentDBData().sDataSource.isEmpty() || + xConfigItem->GetCurrentDBData().sCommand.isEmpty() || + (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 SwView::EnsureMailMergeConfigItem(const SfxItemSet* pArgs) +{ + // create if it does not exist yet + std::shared_ptr xMMConfig = GetMailMergeConfigItem(); + if (!xMMConfig) + { + xMMConfig = std::make_shared(); + xMMConfig->SetSourceView(this); + + //set the first used database as default source on the config item + const SfxPoolItem* pItem = nullptr; + if (pArgs && SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_DATABASE_PROPERTIES, false, &pItem)) + { + //mailmerge has been called from the database beamer + uno::Sequence< beans::PropertyValue> aDBValues; + if (static_cast(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 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 aDBNameList; + std::vector 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 = sDBName.getToken(0, DB_DELIM, nIdx).toInt32(); + //set the currently used database for the wizard + xMMConfig->SetCurrentDBData(aDBData); + } + } + + SetMailMergeConfigItem(xMMConfig); + } + return xMMConfig; +} + +#if HAVE_FEATURE_DBCONNECTIVITY + +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 SfxObjectItem* pItem = static_cast( + pView->GetViewFrame()->GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::SYNCHRON, + { &aURL, &aHidden, &aReferer, &aTargetFrameName })); + SfxShell* pShell = pItem ? pItem->GetShell() : nullptr; + + if(pShell) + { + SfxViewShell* pViewShell = pShell->GetViewShell(); + if(pViewShell) + { + if ((pNewView = dynamic_cast(pViewShell))) + { + pNewView->GetViewFrame()->GetFrame().Appear(); + } + else + { + pViewShell->GetViewFrame()->DoClose(); + } + } + } + } + else + { + SfxStringItem aFactory(SID_NEWDOCDIRECT, SwDocShell::Factory().GetFilterContainer()->GetName()); + const SfxFrameItem* pItem = static_cast( + pView->GetViewFrame()->GetDispatcher()->ExecuteList( + SID_NEWDOCDIRECT, SfxCallMode::SYNCHRON, { &aFactory })); + SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr; + SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr; + pNewView = pViewFrame ? dynamic_cast( pViewFrame->GetViewShell() ) : nullptr; + } + + return pNewView; +} + +class SwMailMergeWizardExecutor : public salhelper::SimpleReferenceObject +{ + SwView* m_pView; // never owner + SwView* m_pView2Close; // never owner + VclPtr m_pWizard; // always owner + VclPtr 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 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 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 xMMConfig = m_pView->EnsureMailMergeConfigItem(pArgs); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig); + + ExecuteWizard(); +} + +void SwMailMergeWizardExecutor::ExecutionFinished() +{ + std::shared_ptr 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 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 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 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 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 xMMConfig = m_pView->GetMailMergeConfigItem(); + if (xMMConfig) + { + if (xMMConfig->GetTargetView()) + { + xMMConfig->GetTargetView()->GetViewFrame()->DoClose(); + xMMConfig->SetTargetView(nullptr); + } + if (xMMConfig->GetSourceView()) + { + auto pViewFrame(xMMConfig->GetSourceView()->GetViewFrame()); + pViewFrame->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(static_cast(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( pActView ) != nullptr; + ::SetDfltMetric(eUnit, bWebView); + } + break; + default:;//prevent warning + } + } + break; + + case FN_SET_MODOPT_TBLNUMFMT: + { + bool bWebView = dynamic_cast( ::GetActiveView() )!= nullptr , + bSet; + + if( pArgs && SfxItemState::SET == pArgs->GetItemState( + nWhich, false, &pItem )) + bSet = static_cast(pItem)->GetValue(); + else + bSet = !m_pModuleConfig->IsInsTableFormatNum( bWebView ); + + m_pModuleConfig->SetInsTableFormatNum( bWebView, bSet ); + } + break; +#if HAVE_FEATURE_DBCONNECTIVITY + 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(); + const std::shared_ptr& 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 vSelection({ uno::makeAny(xConfigItem->GetResultSetPosition()) }); + svx::ODataAccessDescriptor aDescriptor(::comphelper::InitPropertySequence({ + {"Selection", uno::makeAny(vSelection)}, + {"DataSourceName", uno::makeAny(rDBData.sDataSource)}, + {"Command", uno::makeAny(rDBData.sCommand)}, + {"CommandType", uno::makeAny(rDBData.nCommandType)}, + {"ActiveConnection", uno::makeAny(xConfigItem->GetConnection().getTyped())}, + {"Filter", uno::makeAny(xConfigItem->GetFilter())}, + {"Cursor", uno::makeAny(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: + { + std::shared_ptr xConfigItem = SwDBManager::PerformMailMerge(GetActiveView()); + + if (xConfigItem && xConfigItem->GetTargetView()) + xConfigItem->GetTargetView()->GetViewFrame()->GetFrame().Appear(); + } + break; + case FN_MAILMERGE_SAVE_DOCUMENTS: + case FN_MAILMERGE_PRINT_DOCUMENTS: + case FN_MAILMERGE_EMAIL_DOCUMENTS: + { + std::shared_ptr xConfigItem = GetActiveView()->GetMailMergeConfigItem(); + if(!xConfigItem) + return; + xConfigItem->SetTargetView(nullptr); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + switch (nWhich) + { + case FN_MAILMERGE_SAVE_DOCUMENTS: pFact->ExecuteMMResultSaveDialog(rReq.GetFrameWeld()); break; + case FN_MAILMERGE_PRINT_DOCUMENTS: pFact->ExecuteMMResultPrintDialog(rReq.GetFrameWeld()); break; + case FN_MAILMERGE_EMAIL_DOCUMENTS: pFact->ExecuteMMResultEmailDialog(rReq.GetFrameWeld()); break; + } + } + break; +#endif + } +} + +// Catch notifications + +// Catch hint for DocInfo +void SwModule::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + if( const SfxEventHint* pEvHint = dynamic_cast( &rHint) ) + { + SwDocShell* pDocSh = dynamic_cast( pEvHint->GetObjShell() ); + if( pDocSh ) + { + SwWrtShell* pWrtSh = pDocSh->GetWrtShell(); + switch( pEvHint->GetEventId() ) + { + case SfxEventHintId::LoadFinished: + // if it is a new document created from a template, + // update fixed fields + if (pDocSh->GetMedium()) + { + const SfxBoolItem* pTemplateItem = SfxItemSet::GetItem(pDocSh->GetMedium()->GetItemSet(), 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); + pDocSh->GetDoc()->getIDocumentFieldsAccess().SetFixFields(nullptr); + } + } + break; + case SfxEventHintId::CreateDoc: + // Update all FIX-Date/Time fields + if( pWrtSh ) + { + const SfxUInt16Item* pUpdateDocItem = SfxItemSet::GetItem(pDocSh->GetMedium()->GetItemSet(), 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 aDBNameList; + pDoc->GetAllUsedDB( aDBNameList ); + if(!aDBNameList.empty()) + { // Open database beamer + ShowDBObj(pWrtSh->GetView(), pDoc->GetDBData()); + } + } + } + break; + default: break; + } + } + } + else if(const SfxItemSetHint* pSfxItemSetHint = dynamic_cast(&rHint)) + { + if( SfxItemState::SET == pSfxItemSetHint->GetItemSet().GetItemState(SID_ATTR_PATHNAME)) + { + ::GetGlossaries()->UpdateGlosPath( false ); + SwGlossaryList* pList = ::GetGlossaryList(); + if(pList->IsActive()) + pList->Update(); + } + } + 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 ) +{ + if( pBrdCst == m_pUserOptions.get() ) + { + m_bAuthorInitialised = false; + } + else if ( pBrdCst == m_pColorConfig.get() || pBrdCst == m_pAccessibilityOptions.get() ) + { + bool bAccessibility = false; + if( pBrdCst == m_pColorConfig.get() ) + SwViewOption::ApplyColorConfigValues(*m_pColorConfig); + else + bAccessibility = true; + + //invalidate all edit windows + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while(pViewShell) + { + if(pViewShell->GetWindow()) + { + if(dynamic_cast< const SwView *>( pViewShell ) != nullptr || + dynamic_cast< const SwPagePreview *>( pViewShell ) != nullptr || + dynamic_cast< const SwSrcView *>( pViewShell ) != nullptr) + { + if(bAccessibility) + { + if(dynamic_cast< const SwView *>( pViewShell ) != nullptr) + static_cast(pViewShell)->ApplyAccessibilityOptions(*m_pAccessibilityOptions); + else if(dynamic_cast< const SwPagePreview *>( pViewShell ) != nullptr) + static_cast(pViewShell)->ApplyAccessibilityOptions(*m_pAccessibilityOptions); + } + pViewShell->GetWindow()->Invalidate(); + } + } + pViewShell = SfxViewShell::GetNext( *pViewShell ); + } + } + else if( pBrdCst == m_pCTLOptions.get() ) + { + const SfxObjectShell* pObjSh = SfxObjectShell::GetFirst(); + while( pObjSh ) + { + if( auto pDocShell = dynamic_cast(pObjSh) ) + { + SwDoc* pDoc = const_cast(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::ApplyColorConfigValues(*m_pColorConfig); + m_pColorConfig->AddListener(this); + } + return *m_pColorConfig; +} + +SvtAccessibilityOptions& SwModule::GetAccessibilityOptions() +{ + if(!m_pAccessibilityOptions) + { + m_pAccessibilityOptions.reset(new SvtAccessibilityOptions); + m_pAccessibilityOptions->AddListener(this); + } + return *m_pAccessibilityOptions; +} + +SvtCTLOptions& SwModule::GetCTLOptions() +{ + if(!m_pCTLOptions) + { + m_pCTLOptions.reset(new SvtCTLOptions); + m_pCTLOptions->AddListener(this); + } + return *m_pCTLOptions; +} + +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(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 + SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD) ); + xDocSh->DoInitNew(); + + // initialize XForms + static_cast( &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 000000000..c562f3450 --- /dev/null +++ b/sw/source/uibase/app/applab.cxx @@ -0,0 +1,393 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "appenv.hxx" +#include + +using namespace ::com::sun::star; + +const char MASTER_LABEL[] = "MasterLabel"; + +static const SwFrameFormat *lcl_InsertBCText( SwWrtShell& rSh, const SwLabItem& rItem, + SwFrameFormat &rFormat, + sal_uInt16 nCol, sal_uInt16 nRow ) +{ + SfxItemSet aSet( + rSh.GetAttrPool(), svl::Items{}); + 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(nCol) * rItem.m_lHDist, + text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast(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 ) +{ + SfxItemSet aSet( + rSh.GetAttrPool(), svl::Items{}); + 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(nCol) * rItem.m_lHDist, + text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast(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, "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 + // Create DB-Manager + std::unique_ptr> pDBManager(new SwDBManager(nullptr)); +#endif + + // Read SwLabItem from Config + SwLabCfgItem aLabCfg(bLabel); + + // Move up Dialog + SfxItemSet aSet( GetPool(), svl::Items{} ); + aSet.Put( aLabCfg.GetItem() ); + + SwAbstractDialogFactory* pDialogFactory = SwAbstractDialogFactory::Create(); + + ScopedVclPtr pDlg(pDialogFactory->CreateSwLabDlg(rReq.GetFrameWeld(), aSet, +#if HAVE_FEATURE_DBCONNECTIVITY + pDBManager.get(), +#else + NULL, +#endif + bLabel)); + + if ( RET_OK != pDlg->Execute() ) + return; + + // Read dialog, store item in config + const SwLabItem& rItem = static_cast( 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(&*xDocSh); + pDocSh->getIDocumentDeviceAccess().setJobsetup(pPrt->GetJobSetup()); + } + + SfxViewFrame* pViewFrame = SfxViewFrame::DisplayNewDocument( *xDocSh, rReq ); + + SwView *pNewView = static_cast( 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" ); + + { // block for locks the dispatcher!! + + SwWait aWait( static_cast(*xDocSh), true ); + + SET_CURR_SHELL(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 (static_cast(rItem.m_lLeft) ); + aULMargin.SetUpper(static_cast(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 + long lPgWidth, lPgHeight; + lPgWidth = std::max(rItem.m_lPWidth, MINLAY); + lPgHeight = std::max(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(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::unique_ptr pFieldMgr(new SwFieldMgr); + 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, 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( 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 000000000..dcc59d8d0 --- /dev/null +++ b/sw/source/uibase/app/appopt.cxx @@ -0,0 +1,499 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +std::unique_ptr 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( 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 + auto pRet = std::make_unique( + GetPool(), + svl::Items< + 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>{}); + + pRet->Put( SwDocDisplayItem( aViewOpt ) ); + pRet->Put( SwElemItem( aViewOpt ) ); + if( bTextDialog ) + { + pRet->Put( SwShadowCursorItem( aViewOpt )); + pRet->Put( SfxBoolItem(FN_PARAM_CRSR_IN_PROTECTED, aViewOpt.IsCursorInProtectedArea())); + } + + if( pAppView ) + { + SwWrtShell& rWrtShell = pAppView->GetWrtShell(); + + SfxPrinter* pPrt = rWrtShell.getIDocumentDeviceAccess().getPrinter( false ); + if( pPrt ) + pRet->Put(SwPtrItem(FN_PARAM_PRINTER, pPrt)); + pRet->Put(SwPtrItem(FN_PARAM_WRTSHELL, &rWrtShell)); + + pRet->Put(rWrtShell.GetDefault(RES_CHRATR_LANGUAGE).CloneSetWhich(SID_ATTR_LANGUAGE)); + pRet->Put(rWrtShell.GetDefault(RES_CHRATR_CJK_LANGUAGE).CloneSetWhich(SID_ATTR_CHAR_CJK_LANGUAGE)); + pRet->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("DefaultLocale"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), LATIN); + pRet->Put(SvxLanguageItem(nLang, SID_ATTR_LANGUAGE)); + + aLang = aLinguCfg.GetProperty("DefaultLocale_CJK"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), ASIAN); + pRet->Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CJK_LANGUAGE)); + + aLang = aLinguCfg.GetProperty("DefaultLocale_CTL"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), COMPLEX); + pRet->Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CTL_LANGUAGE)); + } + if(bTextDialog) + pRet->Put(SwPtrItem(FN_PARAM_STDFONTS, GetStdFontConfig())); + if( dynamic_cast( SfxViewShell::Current())!=nullptr ) + { + SfxBoolItem aBool(SfxBoolItem(SID_PRINTPREVIEW, true)); + pRet->Put(aBool); + } + + FieldUnit eUnit = pPref->GetHScrollMetric(); + if(pAppView) + pAppView->GetHRulerMetric(eUnit); + pRet->Put(SfxUInt16Item( FN_HSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit))); + + eUnit = pPref->GetVScrollMetric(); + if(pAppView) + pAppView->GetVRulerMetric(eUnit); + pRet->Put(SfxUInt16Item( FN_VSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit) )); + pRet->Put(SfxUInt16Item( SID_ATTR_METRIC, static_cast< sal_uInt16 >(pPref->GetMetric()) )); + pRet->Put(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, pPref->IsApplyCharUnit())); + if(bTextDialog) + { + if(pAppView) + { + const SvxTabStopItem& rDefTabs = + pAppView->GetWrtShell().GetDefault(RES_PARATR_TABSTOP); + pRet->Put( SfxUInt16Item( SID_ATTR_DEFTABSTOP, static_cast(::GetTabDist(rDefTabs)))); + } + else + pRet->Put(SfxUInt16Item( SID_ATTR_DEFTABSTOP, static_cast(convertMm100ToTwip(pPref->GetDefTabInMm100())))); + } + + // 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( static_cast(rSnapSize.Width() )); + aGridItem.SetFieldDrawY( static_cast(rSnapSize.Height())); + + aGridItem.SetFieldDivisionX( aViewOpt.GetDivisionX()); + aGridItem.SetFieldDivisionY( aViewOpt.GetDivisionY()); + + pRet->Put(aGridItem); + + // Options for PrintTabPage + const SwPrintData* pOpt = GetPrtOptions(!bTextDialog); + SwAddPrinterItem aAddPrinterItem(*pOpt ); + pRet->Put(aAddPrinterItem); + + // Options for Web + if(!bTextDialog) + { + pRet->Put(SvxBrushItem(aViewOpt.GetRetoucheColor(), RES_BACKGROUND)); + pRet->Put(SfxUInt16Item(SID_HTML_MODE, HTMLMODE_ON)); + } + + return pRet; +} + +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( pAppView ) != nullptr; + if(bWebView == bTextDialog) + pAppView = nullptr; + } + + SwViewOption aViewOpt = *GetUsrPref(!bTextDialog); + SwMasterUsrPref* pPref = bTextDialog ? m_pUsrPref.get() : m_pWebUsrPref.get(); + + const SfxPoolItem* pItem; + SfxBindings *pBindings = pAppView ? &pAppView->GetViewFrame()->GetBindings() + : nullptr; + + // Interpret the page Documentview + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_DOCDISP, false, &pItem )) + { + const SwDocDisplayItem* pDocDispItem = static_cast(pItem); + + if(!aViewOpt.IsViewMetaChars()) + { + if( (!aViewOpt.IsTab( true ) && pDocDispItem->bTab) || + (!aViewOpt.IsBlank( true ) && pDocDispItem->bSpace) || + (!aViewOpt.IsShowBookmarks(true) && pDocDispItem->bBookmarks) || + (!aViewOpt.IsParagraph( true ) && pDocDispItem->bParagraphEnd) || + (!aViewOpt.IsLineBreak( true ) && pDocDispItem->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 + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_ELEM, false, &pItem ) ) + { + const SwElemItem* pElemItem = static_cast(pItem); + pElemItem->FillViewOptions( aViewOpt ); + + } + + if( SfxItemState::SET == rSet.GetItemState(SID_ATTR_METRIC, false, &pItem ) ) + { + SfxGetpApp()->SetOptions(rSet); + PutItem(*pItem); + const SfxUInt16Item* pMetricItem = static_cast(pItem); + ::SetDfltMetric(static_cast(pMetricItem->GetValue()), !bTextDialog); + } + if( SfxItemState::SET == rSet.GetItemState(SID_ATTR_APPLYCHARUNIT, + false, &pItem ) ) + { + SfxGetpApp()->SetOptions(rSet); + const SfxBoolItem* pCharItem = static_cast(pItem); + ::SetApplyCharUnit(pCharItem->GetValue(), !bTextDialog); + } + + if( SfxItemState::SET == rSet.GetItemState(FN_HSCROLL_METRIC, false, &pItem ) ) + { + const SfxUInt16Item* pMetricItem = static_cast(pItem); + FieldUnit eUnit = static_cast(pMetricItem->GetValue()); + pPref->SetHScrollMetric(eUnit); + if(pAppView) + pAppView->ChangeTabMetric(eUnit); + } + + if( SfxItemState::SET == rSet.GetItemState(FN_VSCROLL_METRIC, false, &pItem ) ) + { + const SfxUInt16Item* pMetricItem = static_cast(pItem); + FieldUnit eUnit = static_cast(pMetricItem->GetValue()); + pPref->SetVScrollMetric(eUnit); + if(pAppView) + pAppView->ChangeVRulerMetric(eUnit); + } + + if( SfxItemState::SET == rSet.GetItemState(SID_ATTR_DEFTABSTOP, false, &pItem ) ) + { + sal_uInt16 nTabDist = static_cast(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( SfxItemState::SET == rSet.GetItemState( SID_ATTR_GRID_OPTIONS, false, &pItem )) + { + const SvxGridItem* pGridItem = static_cast(pItem); + + 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(pGridItem->GetFieldDivisionX()) ; + if( aViewOpt.GetDivisionX() != nDiv ) + aViewOpt.SetDivisionX( nDiv ); + nDiv = static_cast(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( SfxItemState::SET == rSet.GetItemState( FN_PARAM_ADDPRINTER, false, &pItem )) + { + SwPrintOptions* pOpt = GetPrtOptions(!bTextDialog); + if (pOpt) + { + const SwAddPrinterItem* pAddPrinterAttr = static_cast(pItem); + *pOpt = *pAddPrinterAttr; + } + + } + + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_SHADOWCURSOR, false, &pItem )) + { + static_cast(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( SfxItemState::SET == rSet.GetItemState( FN_PARAM_CRSR_IN_PROTECTED, false, &pItem )) + { + aViewOpt.SetCursorInProtectedArea(static_cast(pItem)->GetValue()); + } + + // set elements for the current view and shell + ApplyUsrPref( aViewOpt, pAppView, bTextDialog? SvViewOpt::DestText : SvViewOpt::DestWeb); +} + +std::unique_ptr SwModule::CreateTabPage( sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ) +{ + std::unique_ptr 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( 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 000000000..aeb522be5 --- /dev/null +++ b/sw/source/uibase/app/docsh.cxx @@ -0,0 +1,1412 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ShellClass_SwDocShell +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +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 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; + ErrCode 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; + const SfxPoolItem* pApiItem; + const SfxItemSet* pMedSet; + if( nullptr != ( pMedSet = rMedium.GetItemSet() ) && SfxItemState::SET == + pMedSet->GetItemState( FN_API_CALL, true, &pApiItem ) ) + bAPICall = static_cast(pApiItem)->GetValue(); + + std::shared_ptr pFlt = rMedium.GetFilter(); + if( !pFlt ) + { + if(!bAPICall) + { + std::unique_ptr 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 = SfxItemSet::GetItem(rMedium.GetItemSet(), 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; + const SfxItemSet* pSet; + const SfxPoolItem* pItem; + if( nullptr != ( pSet = rMedium.GetItemSet() ) && SfxItemState::SET == + pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) ) + aOpt.ReadUserData( static_cast(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 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(); + + ErrCode 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 , 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); + } + + ErrCode nErr = ERR_SWG_WRITE_ERROR, nVBWarning = ERRCODE_NONE; + if( SfxObjectShell::Save() ) + { + switch( GetCreateMode() ) + { + case SfxObjectCreateMode::INTERNAL: + nErr = ERRCODE_NONE; + break; + + case SfxObjectCreateMode::ORGANIZER: + { + WriterRef xWrt; + ::GetXMLWriter(OUString(), 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(*this) ); + m_xDoc->SetContainsMSVBasic( false ); + } + + // End TableBox Edit! + if (m_pWrtShell) + m_pWrtShell->EndAllTableBoxEdit(); + + WriterRef xWrt; + ::GetXMLWriter(OUString(), 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::LockAllViewsGuard(SwViewShell* pViewShell) +{ + if (!pViewShell) + return; + for (SwViewShell& rShell : pViewShell->GetRingContainer()) + { + if (!rShell.IsViewLocked()) + { + m_aViewWasUnLocked.push_back(&rShell); + rShell.LockView(true); + } + } +} + +SwDocShell::LockAllViewsGuard::~LockAllViewsGuard() +{ + for (SwViewShell* pShell : m_aViewWasUnLocked) + pShell->LockView(false); +} + +std::unique_ptr SwDocShell::LockAllViews() +{ + return std::make_unique(GetEditShell()); +} + +// Save using the Defaultformat +bool SwDocShell::SaveAs( SfxMedium& rMedium ) +{ + SwWait aWait( *this, true ); + // tdf#41063: prevent jumping to cursor at any temporary modification + auto aViewGuard(LockAllViews()); + //#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 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 xDPS( + GetModel(), uno::UNO_QUERY_THROW); + uno::Reference 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 + = SfxItemSet::GetItem(rMedium.GetItemSet(), 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 + = SfxItemSet::GetItem(rMedium.GetItemSet(), SID_SAVETO, false)) + bCopyTo = pSaveToItem->GetValue(); + } + + auto xDatabaseContext = sdb::DatabaseContext::create(xContext); + uno::Reference xDataSource(xDatabaseContext->getByName(aURL), + uno::UNO_QUERY); + if (xDataSource) + { + uno::Reference xStorable(xDataSource->getDatabaseDocument(), + uno::UNO_QUERY); + SwDBManager::StoreEmbeddedDataSource(xStorable, rMedium.GetOutputStorage(), + pMgr->getEmbeddedName(), rMedium.GetName(), + bCopyTo); + } + } + } + + // #i62875# + // reset compatibility flag , 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); + } + + ErrCode nErr = ERR_SWG_WRITE_ERROR, 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(*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 aOldOLELnk( m_xDoc->GetOle2Link() ); + m_xDoc->SetOle2Link( Link() ); + + // Suppress SfxProgress when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( + SfxObjectCreateMode::EMBEDDED == GetCreateMode() ); + + WriterRef xWrt; + ::GetXMLWriter(OUString(), 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( pViewShell ); +} + +bool SwDocShell::ConvertTo( SfxMedium& rMedium ) +{ + std::shared_ptr 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 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 xStg = new SotStorage( rMedium.GetOutStream(), false ); + OSL_ENSURE( !xStg->GetError(), "No storage available for storing VBA macros!" ); + if ( !xStg->GetError() ) + { + nVBWarning = SaveOrDelMSVBAStorage( static_cast(*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 + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + if( !rHtmlOpt.IsStarBasic() && rHtmlOpt.IsStarBasicWarning() && HasBasic() ) + { + uno::Reference< XLibraryContainer > xLibCont = GetBasicContainer(); + uno::Reference< XNameAccess > xLib; + const Sequence aNames = xLibCont->getElementNames(); + for(const OUString& rName : aNames) + { + Any aLib = xLibCont->getByName(rName); + aLib >>= xLib; + if(xLib.is()) + { + Sequence 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 , 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::makeAny( 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; + const SfxItemSet* pSet; + const SfxPoolItem* pItem; + if( nullptr != ( pSet = rMedium.GetItemSet() ) ) + { + if( SfxItemState::SET == pSet->GetItemState( SID_FILE_FILTEROPTIONS, + true, &pItem ) ) + sItemOpt = static_cast(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 + ErrCode nErrno; + const OUString aFileName( rMedium.GetName() ); + + // No View, so the whole Document! + if (m_pWrtShell && !Application::IsHeadlessModeEnabled()) + { + 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, true ); + 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 ) +{ + //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 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); + 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 ); + 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 ( dynamic_cast( pTmpFrame->GetViewShell() ) && + static_cast(pTmpFrame->GetViewShell())->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( 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(GetView()) + : SfxViewShell::Current(); + bool bSourceView = dynamic_cast( 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(this) != nullptr + || GetObjectShell()->isExportLocked()) + rSet.DisableItem( nWhich ); + break; + + case FN_NEW_HTML_DOC: + if (dynamic_cast(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() + : ::utl::MiscCfg().GetYear2000() ))); + } + 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(), + "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( 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 no longer works, because + // 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 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( 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 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 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 ); +} + +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" +}; +static 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 ) +{ + RedlineFlags nOn = bActivate ? RedlineFlags::On : RedlineFlags::NONE; + RedlineFlags nMode = m_pWrtShell->GetRedlineFlags(); + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn ); +} + +void SwDocShell::SetProtectionPassword( const OUString &rNewPassword ) +{ + const SfxAllItemSet aSet( GetPool() ); + const SfxPoolItem* pItem = nullptr; + + IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); + Sequence< sal_Int8 > aPasswd = rIDRA.GetRedlinePassword(); + if (SfxItemState::SET == aSet.GetItemState(FN_REDLINE_PROTECT, false, &pItem) + && static_cast(pItem)->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() ); + const SfxPoolItem* pItem = nullptr; + + IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); + const Sequence< sal_Int8 >& aPasswdHash( rIDRA.GetRedlinePassword() ); + if (SfxItemState::SET == aSet.GetItemState(FN_REDLINE_PROTECT, false, &pItem) + && static_cast(pItem)->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 000000000..e70129d99 --- /dev/null +++ b/sw/source/uibase/app/docsh2.cxx @@ -0,0 +1,1745 @@ +/* -*- 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +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 SwDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet) +{ + std::shared_ptr xDlg = std::make_shared(pParent, rSet); + //only with statistics, when this document is being shown, not + //from within the Doc-Manager + SwDocShell* pDocSh = static_cast( 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 ( const SfxEventHint* pSfxEventHint = dynamic_cast(&rHint) ) + { + uno::Sequence< uno::Any > aArgs; + switch( pSfxEventHint->GetEventId() ) + { + case SfxEventHintId::CreateDoc: + xVbaEvents->processVbaEvent( DOCUMENT_NEW, aArgs ); + break; + case SfxEventHintId::OpenDoc: + 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 ( const SfxEventHint* pSfxEventHint = dynamic_cast(&rHint) ) + { + switch( pSfxEventHint->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( pSfxEventHint->GetEventId() ) + { + case SfxEventHintId::CreateDoc: + { + uno::Any aDocument; + aDocument <<= mxAutomationDocumentObject; + uno::Sequence< uno::Any > aArgs(1); + aArgs[0] = aDocument; + SW_MOD()->CallAutomationApplicationEventSinks( "NewDocument", aArgs ); + } + break; + case SfxEventHintId::OpenDoc: + { + uno::Any aDocument; + aDocument <<= mxAutomationDocumentObject; + uno::Sequence< uno::Any > aArgs(1); + aArgs[0] = aDocument; + SW_MOD()->CallAutomationApplicationEventSinks( "DocumentOpen", aArgs ); + } + break; + default: + break; + } + } + + sal_uInt16 nAction = 0; + auto pEventHint = dynamic_cast(&rHint); + if( pEventHint && pEventHint->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 ) + { + 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 + // it has to be assured, that it's not modified. + // Perform the same as for action id 1, but disable . + 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(2); + // Arg 0: Document + aArgs[0] = aDocument; + // Arg 1: Cancel + aArgs[1] <<= 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( 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(); + + SfxItemSet aSet( pApp->GetPool(), svl::Items{} ); + aSet.Put( aSwOptions ); + + const SfxPoolItem* pOpenSmartTagOptionsItem = nullptr; + if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_OPEN_SMARTTAGOPTIONS, false, &pOpenSmartTagOptionsItem ) ) + aSet.Put( *static_cast(pOpenSmartTagOptionsItem) ); + + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + VclPtr 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(SfxObjectShell::GetFirst(checkSfxObjectShell)); + pDocSh; + pDocSh = static_cast(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell )) ) + { + 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 = typeid(SwPagePreview) == typeid( pViewShell ); + + while( pTmpFrame ) // search Preview + { + if( typeid(SwView) == typeid( pTmpFrame->GetViewShell()) ) + bOnly = false; + else if( typeid(SwPagePreview) == typeid( 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(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; + sal_uInt16 nRet = USHRT_MAX; + + 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(SID_TEMPLATE_NAME); + if ( pTemplateItem ) + { + aFileName = pTemplateItem->GetValue(); + const SfxInt32Item* pFlagsItem = rReq.GetArg(SID_TEMPLATE_LOAD); + if ( pFlagsItem ) + nFlags = static_cast(static_cast(pFlagsItem->GetValue())); + } + } + + if ( aFileName.isEmpty() ) + { + SvtPathOptions aPathOpt; + SfxNewFileDialog aNewFileDlg(GetView()->GetFrameWeld(), SfxNewFileDialogMode::LoadTemplate); + aNewFileDlg.SetTemplateFlags(nFlags); + + nRet = aNewFileDlg.run(); + if(RET_TEMPLATE_LOAD == nRet) + { + FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetView()->GetFrameWeld()); + uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + xFP->setDisplayDirectory( aPathOpt.GetWorkPath() ); + + SfxObjectFactory &rFact = GetFactory(); + SfxFilterMatcher aMatcher( rFact.GetFactoryName() ); + SfxFilterMatcherIter aIter( aMatcher ); + std::shared_ptr 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 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(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 ( !GetError() ) + rReq.Done(); + } + } + break; + case SID_SOURCEVIEW: + { + SfxViewShell* pViewShell = GetView() + ? static_cast(GetView()) + : SfxViewShell::Current(); + SfxViewFrame* pViewFrame = 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 pHtmlFlt = + SwIoSystem::GetFilterOfFormat( + "HTML", + SwWebDocShell::Factory().GetFilterContainer() ); + bool bLocalHasName = HasName(); + if(bLocalHasName) + { + //check for filter type + std::shared_ptr pFlt = GetMedium()->GetFilter(); + if(!pFlt || pFlt->GetUserData() != pHtmlFlt->GetUserData()) + { + std::unique_ptr xBuilder(Application::CreateBuilder(pViewFrame->GetWindow().GetFrameWeld(), "modules/swriter/ui/saveashtmldialog.ui")); + std::unique_ptr 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.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 SfxBoolItem* pBool = static_cast( + pViewFrame->GetDispatcher()->ExecuteList( + SID_SAVEASDOC, SfxCallMode::SYNCHRON, + { &aName, &aFilter })); + if(!pBool || !pBool->GetValue()) + break; + } + } + + OSL_ENSURE(dynamic_cast(this), + "SourceView only in WebDocShell"); + + // the SourceView is not the 1 for SwWebDocShell + sal_uInt16 nSlot = SID_VIEWSHELL1; + bool bSetModified = false; + VclPtr pSavePrinter; + if( nullptr != pSrcView) + { + SfxPrinter* pTemp = GetDoc()->getIDocumentDeviceAccess().getPrinter( false ); + if(pTemp) + pSavePrinter = VclPtr::Create(*pTemp); + bSetModified = IsModified() || pSrcView->IsModified(); + if(pSrcView->IsModified()||pSrcView->HasSourceSaved()) + { + utl::TempFile 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) + pViewFrame->GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON); + if(bSetModified) + GetDoc()->getIDocumentState().SetModified(); + if(pSavePrinter) + { + GetDoc()->getIDocumentDeviceAccess().setPrinter( pSavePrinter, true, true); + //pSavePrinter must not be deleted again + } + pViewFrame->GetBindings().SetState(SfxBoolItem(SID_SOURCEVIEW, false)); // not SID_VIEWSHELL2 + pViewFrame->GetBindings().Invalidate( SID_NEWWINDOW ); + pViewFrame->GetBindings().Invalidate( SID_BROWSER_MODE ); + pViewFrame->GetBindings().Invalidate( FN_PRINT_LAYOUT ); + } + break; + case SID_GET_COLORLIST: + { + const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE); + const XColorListRef& pList = pColItem->GetColorList(); + rReq.SetReturnValue(OfaRefItem(SID_GET_COLORLIST, pList)); + } + break; + case FN_ABSTRACT_STARIMPRESS: + case FN_ABSTRACT_NEWDOC: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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(OUString(), OUString(), xWrt); + SvMemoryStream *pStrm = new SvMemoryStream(); + pStrm->SetBufferSize( 16348 ); + SwWriter aWrt( *pStrm, *pSmryDoc ); + ErrCode 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(1); + aArgs[0].Name = "RtfOutline"; + aArgs[0].Value <<= 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( 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( OUString('O'), OUString(), xWrt ); + std::unique_ptr pStrm (new SvMemoryStream()); + pStrm->SetBufferSize( 16348 ); + SwWriter aWrt( *pStrm, *GetDoc() ); + ErrCode 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(1); + aArgs[0].Name = "RtfOutline"; + aArgs[0].Value <<= aSeq; + xHelper->executeDispatch( xProv, "SendOutlineToImpress", OUString(), 0, aArgs ); + } + } + else + { + rtl::Reference pClipCntnr = new TransferDataContainer; + + pClipCntnr->CopyAnyData( SotClipboardFormatId::RTF, static_cast( + 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 ); + break; + + case SID_MAIL_PREPAREEXPORT: + { + //pWrtShell is not set in page preview + if (m_pWrtShell) + m_pWrtShell->StartAllAction(); + 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(pItem)->GetValue(); + const SfxStringItem* pTemplItem = SfxItemSet::GetItem(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()); + + 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 pFlt; + const char* pStrId; + + if( bCreateHtml ) + { + // for HTML there is only one filter!! + pFlt = SwIoSystem::GetFilterOfFormat( + "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 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 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::get()); + + xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + ListboxControlActions::ADD_ITEMS , aTemplates ); + Any aSelectPos(&nSelect, cppu::UnoType::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 = sTmpl.copy(aOutline.getLength()).toInt32(); //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()) + { + std::unique_ptr pFrameItem(new SfxFrameItem( SID_DOCFRAME, + pViewShell->GetViewFrame() )); + SfxDispatcher* pDispatch = pViewShell->GetDispatcher(); + pDispatch->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON, + { &aName, &aReferer, pFrameItem.get() }); + break; + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + } + } + if( !bDone && !rReq.IsAPI() ) + { + std::unique_ptr 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 )) + { + OSL_ENSURE(dynamic_cast< const SfxUInt16Item *>( pItem ) != nullptr, "wrong Item"); + sal_uInt16 nYear2K = static_cast(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( 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; + + SfxStringItem aApp(SID_DOC_SERVICE, "com.sun.star.text.TextDocument"); + SfxStringItem aTarget(SID_TARGETNAME, "_blank"); + pViewShell->GetDispatcher()->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(pItem)->GetValue(); + auto eType = SfxClassificationPolicyType::IntellectualProperty; + if (pArgs->GetItemState(SID_TYPE_NAME, false, &pItem) == SfxItemState::SET) + { + const OUString& rType = static_cast(pItem)->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: + { + auto xDialog = std::make_shared(GetView()->GetFrameWeld(), false); + + SwWrtShell* pShell = GetWrtShell(); + std::vector aInput = pShell->CollectAdvancedClassification(); + xDialog->setupValues(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: + { + SwWrtShell* pShell = GetWrtShell(); + auto xDialog = std::make_shared(GetView()->GetFrameWeld(), true, [pShell]() + { + pShell->SignParagraph(); + }); + + std::vector aInput = pShell->CollectParagraphClassification(); + xDialog->setupValues(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( pItem )->GetValue() ); + + if ( pArgs->GetItemState( SID_WATERMARK_FONT, false, &pItem ) == SfxItemState::SET ) + aItem.SetFont( static_cast( pItem )->GetValue() ); + if ( pArgs->GetItemState( SID_WATERMARK_ANGLE, false, &pItem ) == SfxItemState::SET ) + aItem.SetAngle( static_cast( pItem )->GetValue() ); + if ( pArgs->GetItemState( SID_WATERMARK_TRANSPARENCY, false, &pItem ) == SfxItemState::SET ) + aItem.SetTransparency( static_cast( pItem )->GetValue() ); + if ( pArgs->GetItemState( SID_WATERMARK_COLOR, false, &pItem ) == SfxItemState::SET ) + aItem.SetColor( Color(static_cast( pItem )->GetValue()) ); + + pSh->SetWatermark( aItem ); + } + else + { + SfxViewShell* pViewShell = GetView() ? GetView() : SfxViewShell::Current(); + SfxBindings& rBindings( pViewShell->GetViewFrame()->GetBindings() ); + auto xDlg = std::make_shared(pViewShell->GetViewFrame()->GetWindow().GetFrameWeld(), + rBindings); + weld::DialogController::runAsync(xDlg, [](sal_Int32 /*nResult*/){}); + } + } + } + break; + case SID_NOTEBOOKBAR: + { + const SfxStringItem* pFile = rReq.GetArg( 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(GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()); + + if (rRedlineAccess.GetRedlineTable().empty()) + { + break; + } + + if (pWrtShell) + { + pWrtShell->StartAllAction(); + } + + rRedlineAccess.AcceptAllRedline(nWhich == FN_REDLINE_ACCEPT_ALL); + + if (pWrtShell) + { + pWrtShell->EndAllAction(); + } + + 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 ) +{ + 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()) + { + 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* pVFrame = GetView()->GetViewFrame(); + SwFieldDlgWrapper *pWrp = static_cast(pVFrame-> + GetChildWindow( SwFieldDlgWrapper::GetChildWindowId() )); + if( pWrp ) + pWrp->ReInitDlg( this ); + + // if necessary newly initialize RedlineDlg + SwRedlineAcceptChild *pRed = static_cast(pVFrame-> + 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. + SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); + //#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( rHtmlOptions.IsStarBasic() && 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, makeAny( 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 xDoc(GetBaseModel(), uno::UNO_QUERY); + text::XTextDocument* pxDoc = xDoc.get(); + static_cast(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(GetView()) + : SfxViewShell::Current(); + SfxViewFrame* pViewFrame = pViewShell->GetViewFrame(); + pViewFrame->GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::SYNCHRON ); + + SubInitNew(); + + SfxMedium aMed( rStreamName, StreamMode::READ ); + // #i48748# - use class , because + // the base URL has to be set to the filename of the document + // and not to the base URL of the temporary file 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(); +} + +ErrCode SwDocShell::LoadStylesFromFile(const OUString& rURL, SwgReaderOption& rOpt, bool bUnoCall) +{ + ErrCode 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 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 xStorage = aMed.GetStorage(); + if ( xStorage.is() ) + { + // use on retrieving in order to check, + // if the storage is one of our own ones. + try + { + uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY_THROW ); + const OUString aMediaTypePropName( "MediaType" ); + xProps->getPropertyValue( aMediaTypePropName ); + bImport = true; + } + catch (const uno::Exception&) + { + bImport = false; + } + } + } + if ( bImport ) + { + Reader* pRead = ReadXML; + SwReaderPtr pReader; + std::unique_ptr 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.reset(new SwPaM( 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, + const OUString& rFileName, + const OUString& rPasswd, + const OUString& rFilter, + sal_Int16 nVersion, + SwDocShell* pDestSh ) +{ + if ( rFileName.isEmpty() ) + return 0; + + // 1. Does the file already exist in the list of all Documents? + INetURLObject aTmpObj( rFileName ); + aTmpObj.SetMark( OUString() ); + + // 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 ); + + 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(pItem)->GetValue()) + : !nVersion ) + { + // Found, thus return + xDocSh = pShell; + return 1; + } + } + + if( bFirst ) + { + bFirst = false; + pShell = SfxObjectShell::GetFirst( checkSfxObjectShell ); + } + else + pShell = SfxObjectShell::GetNext( *pShell, checkSfxObjectShell ); + } + + // 2. Open the file ourselves + std::unique_ptr 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 pSfxFlt; + if (!xMed->GetError()) + { + 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(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 000000000..e9a8b2e31 --- /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 +#include +#include +#include +#include +#include +#include +#include + +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(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.get()); + } + } + + // 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 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 000000000..eb2452150 --- /dev/null +++ b/sw/source/uibase/app/docshini.cxx @@ -0,0 +1,699 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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 + if (!utl::ConfigManager::IsFuzzing()) + { + SvxAsianConfig aAsian; + const Sequence 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 pFontItem; + const SvxLanguageItem& rLang = static_cast(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 + }; + + sal_uInt16 nFontWhich = RES_CHRATR_FONT; + sal_uInt16 nFontHeightWhich = RES_CHRATR_FONTSIZE; + LanguageType eLanguage = m_xDoc->GetDefault( RES_CHRATR_LANGUAGE ).GetLanguage(); + for(sal_uInt8 nIdx = 0; nIdx < 24; 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( static_cast(pColl->GetFormatAttr( nFontHeightWhich ))); + if(aFontHeight.GetHeight() != sal::static_int_cast(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() ); + } + + /* #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 + // at the document instance, the document is modified. Thus, reset this + // status here. Note: In method 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 *const pD, SfxObjectCreateMode const eMode ) + : SfxObjectShell(eMode) + , m_xDoc(pD) + , 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(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(xDoc.get())->Invalidate(); + if (m_xDoc) + { + if (m_xBasePool.is()) + { + static_cast(m_xBasePool.get())->dispose(); + m_xBasePool.clear(); + } + m_xDoc->SetOle2Link(Link()); + 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(xDoc.get())->Invalidate(); +} +void SwDocShell::ReactivateModel() +{ + // disconnect Uno-Object + uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY); + static_cast(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)) + { + // legacy processing for tdf#99729 + if (m_xDoc->getIDocumentDrawModelAccess().GetDrawModel()) + m_xDoc->getIDocumentDrawModelAccess().GetDrawModel()->SetAnchoredTextOverflowLegacy( + true); + // legacy behaviour (not hiding paragraph) for Database (MailMerge) fields + m_xDoc->GetDocumentSettingManager().set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA, + false); + } + + // 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 = SfxItemSet::GetItem(rMedium.GetItemSet(), SID_UPDATEDOCMODE, false); + m_nUpdateDocMode = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE; + } + + SwWait aWait( *this, true ); + ErrCode 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 + ErrCode 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; + + sal_uInt16 nRange[] = { + RES_PARATR_ADJUST, RES_PARATR_ADJUST, + 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, + 0, 0, 0 }; + if(!bWeb) + { + nRange[ SAL_N_ELEMENTS(nRange) - 3 ] = RES_PARATR_TABSTOP; + nRange[ SAL_N_ELEMENTS(nRange) - 2 ] = RES_PARATR_HYPHENZONE; + } + SfxItemSet aDfltSet( m_xDoc->GetAttrPool(), nRange ); + + //! get lingu options without loading lingu DLL + SvtLinguOptions aLinguOpt; + + if (!utl::ConfigManager::IsFuzzing()) + 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); + + aDfltSet.Put( aHyp ); + + sal_uInt16 nNewPos = static_cast< sal_uInt16 >(convertMm100ToTwip(SW_MOD()->GetUsrPref(false)->GetDefTabInMm100())); + 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() ) + { + 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 000000000..6886b548b --- /dev/null +++ b/sw/source/uibase/app/docst.cxx @@ -0,0 +1,1547 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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* pFrame = pShell->GetView().GetViewFrame(); + std::unique_ptr pItem; + pFrame->GetBindings().QueryState(SID_STYLE_FAMILY, pItem); + SfxUInt16Item* pFamilyItem = dynamic_cast(pItem.get()); + if (pFamilyItem) + { + nActualFamily = static_cast(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 + { + 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()) + { + SwTextFormatColl* pColl = pShell->GetCurTextFormatColl(); + if(pColl) + aName = pColl->GetName(); + + SfxTemplateItem aItem(nWhich, aName); + + 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: + { + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !rHtmlOpt.IsPrintLayoutExtension()) + 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(static_cast(pItem)->GetValue()); + + OUString sName; + SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto; + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_NEW, + false, &pItem )) + sName = static_cast(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_MASK, + false, &pItem )) + nMask = static_cast(static_cast(pItem)->GetValue()); + OUString sParent; + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_REFERENCE, + false, &pItem )) + sParent = static_cast(pItem)->GetValue(); + + if (sName.isEmpty() && m_xBasePool) + sName = SfxStyleDialogController::GenerateUnusedName(*m_xBasePool, nFamily); + + Edit(sName, sParent, nFamily, nMask, true, OString(), 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(SID_APPLY_STYLE); + const SfxStringItem* pFamilyItem = rReq.GetArg(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_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: + { + SwTextFormatColl* pColl = GetWrtShell()->GetCurTextFormatColl(); + if(pColl) + { + aParam = pColl->GetName(); + 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(pItem)->GetValue(); + + if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILY, + false, &pItem )) + nFamily = static_cast(static_cast(pItem)->GetValue()); + + if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILYNAME, false, &pItem )) + { + OUString aFamily = static_cast(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(static_cast(pItem)->GetValue()); + if( SfxItemState::SET == pArgs->GetItemState(FN_PARAM_WRTSHELL, + false, &pItem )) + pActShell = pShell = static_cast(static_cast(pItem)->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(SfxItemState::SET == pArgs->GetItemState(SID_STYLE_UPD_BY_EX_NAME, false, &pItem)) + { + aParam = static_cast(pItem)->GetValue(); + } + break; + case SfxStyleFamily::Table: + if(SfxItemState::SET == pArgs->GetItemState(SID_STYLE_UPD_BY_EX_NAME, false, &pItem)) + { + aParam = static_cast(pItem)->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: + Edit(aParam, OUString(), nFamily, nMask, false, OString(), 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(ApplyStyles(aParam, nFamily, pActShell, rReq.GetModifier() )); + bReturns = true; + break; + case SID_STYLE_WATERCAN: + nRet = static_cast(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"); + } + + 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 > const & xTmp, + SfxStyleFamily nFamily, SfxAbstractApplyTabDialog *pDlg, + rtl::Reference< SfxStyleSheetBasePool > const & xBasePool, + bool bModified) + : m_pDlg(pDlg) + , m_rDocSh(rDocSh) + , m_bNew(bNew) + , m_xTmp(xTmp) + , m_nFamily(nFamily) + , m_xBasePool(xBasePool) + , m_bModified(bModified) + { + } + DECL_LINK( ApplyHdl, LinkParamNone*, void ); + void apply() + { + ApplyHdl(nullptr); + } + VclPtr m_pDlg; +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() ); + ::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, true ); + } + else + { + if(SfxStyleFamily::Page == m_nFamily) + { + static const sal_uInt16 aInval[] = { + SID_IMAGE_ORIENTATION, + SID_ATTR_CHAR_FONT, + FN_INSERT_CTRL, FN_INSERT_OBJ_CTRL, 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 ); + + if( SfxStyleFamily::Page == m_nFamily && SvtLanguageOptions().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_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); + } + } + + 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(); + } + + 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 xStyleFamilies = xStyleFamSupp->getStyleFamilies(); + + if (!xStyleFamilies.is()) + return; + + uno::Reference xPageStyles(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + + if (!xPageStyles.is()) + return; + + uno::Reference xEndnotePageStyle(xPageStyles->getByName("Endnote"), + uno::UNO_QUERY); + + if (!xEndnotePageStyle.is()) + return; + + // Language-independent name of the "Default Style" is "Standard" + uno::Reference xDefaultPageStyle(xPageStyles->getByName("Standard"), + uno::UNO_QUERY); + if (!xDefaultPageStyle.is()) + return; + + if (xEndnotePageStyle->isUserDefined() || !xEndnotePageStyle->isInUse()) + return; + + uno::Reference xEndnotePagePropSet(xPageStyles->getByName("Endnote"), uno::UNO_QUERY); + uno::Reference 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( + xDefaultPagePropSet->getPropertyValue("IsLandscape")); + auto const bIsEndLandScape = *o3tl::doAccess( + 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( + const OUString &rName, + const OUString &rParent, + const SfxStyleFamily nFamily, + SfxStyleSearchBits nMask, + const bool bNew, + const OString& 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(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 ); + + /*When a new paragraph style is created based on a "to outline style + assigned" paragraph style, the outline level attribute and the list + style attribute of the new paragraph style have to be set to 0 + respectively "".*/ + if (pColl && pColl->IsAssignedToListLevelOfOutlineStyle()) + { + SwNumRuleItem aItem; + pDStyle->GetCollection()->SetFormatAttr( aItem ); + pDStyle->GetCollection()->SetAttrOutlineLevel( 0 ); + } + } + 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(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 ); + } + 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)); + } + + 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. + SwWrtShell* pCurrShell = pActShell ? pActShell : m_pWrtShell; + 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(); + VclPtr pDlg(pFact->CreateTemplateDialog(GetView()->GetFrameWeld(), + *xTmp, nFamily, sPage, pCurrShell, bNew)); + auto pApplyStyleHelper = std::make_shared(*this, bNew, xTmp, nFamily, pDlg.get(), m_xBasePool, bModified); + pDlg->SetApplyHdl(LINK(pApplyStyleHelper.get(), ApplyStyle, ApplyHdl)); + + std::shared_ptr pRequest; + if (pReq) + { + pRequest = std::make_shared(*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, bModified, 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(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(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(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); + } + + if (RET_OK != nResult) + { + if (bNew) + { + GetWrtShell()->Undo(); + m_xDoc->GetIDocumentUndoRedo().ClearRedo(); + } + + if (!bModified) + 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 && bModified) + { + 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() ); + 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(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( 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: + { + // #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(); + 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( 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(pStyle->GetPageDesc()); + break; + case SfxStyleFamily::Pseudo: + aTemplate.aColl.pNumRule = const_cast(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( 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: + { + + SwTableAutoFormat aFormat(rName); + if (pCurrWrtShell->GetTableAutoFormat(aFormat)) + { + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->GetDoc()->ChgTableStyle(rName, aFormat); + pCurrWrtShell->EndAllAction(); + } + + } + break; + default: break; + } +} + +// NewByExample +void SwDocShell::MakeByExample( const OUString &rName, SfxStyleFamily nFamily, + SfxStyleSearchBits nMask, SwWrtShell* pShell ) +{ + SwWrtShell* pCurrWrtShell = pShell ? pShell : GetWrtShell(); + SwDocStyleSheet* pStyle = static_cast( 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(&m_xBasePool->Make(rName, nFamily, nMask)); + } + else + { + pStyle = static_cast(&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(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(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(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( + 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(pCurrWrtShell->GetPageDesc( nPgDsc )); + SwPageDesc& rDest = *const_cast(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; + } +} + +sfx::AccessibilityIssueCollection SwDocShell::runAccessibilityCheck() +{ + sw::AccessibilityCheck aCheck(m_xDoc.get()); + aCheck.check(); + return aCheck.getIssueCollecton(); +} + +std::set SwDocShell::GetDocColors() +{ + return m_xDoc->GetDocColors(); +} + +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( &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(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(rSource).m_xDoc ); + m_pWrtShell->EndAllAction(); + } + else + { + bool bModified = m_xDoc->getIDocumentState().IsModified(); + m_xDoc->ReplaceStyles( *static_cast(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( + const OUString& rPage, + const OString& rPageId, + SwWrtShell& rActShell, + SfxRequest* pRequest) +{ + Edit(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 000000000..693ae7f20 --- /dev/null +++ b/sw/source/uibase/app/docstyle.cxx @@ -0,0 +1,3220 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The Format names in the list of all names have the +// following family as their first character: + +#define cCHAR u'c' +#define cPARA u'p' +#define cFRAME u'f' +#define cPAGE u'g' +#define cNUMRULE u'n' +#define cTABSTYLE u't' +#define cCELLSTYLE u'b' + +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 SwImplShellAction +{ + SwWrtShell* pSh; + std::unique_ptr 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() ) + pSh = rDoc.GetDocShell()->GetWrtShell(); + else + pSh = nullptr; + + if( pSh ) + { + pCurrSh.reset( new CurrShell( pSh ) ); + pSh->StartAllAction(); + } +} + +SwImplShellAction::~SwImplShellAction() COVERITY_NOEXCEPT_FALSE +{ + if( pCurrSh ) + { + pSh->EndAllAction(); + 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, const OUString& 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()) + { + sal_Unicode cStyle(0); + switch( eFam ) + { + case SfxStyleFamily::Char: + cStyle = cCHAR; + break; + case SfxStyleFamily::Para: + cStyle = cPARA; + break; + case SfxStyleFamily::Frame: + cStyle = cFRAME; + break; + case SfxStyleFamily::Page: + cStyle = cPAGE; + break; + case SfxStyleFamily::Pseudo: + cStyle = cNUMRULE; + break; + case SfxStyleFamily::Table: + cStyle = cTABSTYLE; + break; + case SfxStyleFamily::Cell: + cStyle = cCELLSTYLE; + break; + default: + cStyle = ' '; + break; + } + const OUString sSrch = OUStringChar(cStyle) + rName; + + UniqueHash::const_iterator it = maUnique.find(sSrch); + 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 < maImpl.size() ) + 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( char cChar, const OUString& rStr ) +{ + const OUString aStr = OUStringChar(cChar) + rStr; + + UniqueHash::const_iterator it = maUnique.find(aStr); + if (it != maUnique.end()) + return; + + maUnique[aStr] = static_cast(maImpl.size()); + maImpl.push_back(aStr); +} + +// UI-sided implementation of StyleSheets +// uses the Core-Engine +SwDocStyleSheet::SwDocStyleSheet( SwDoc& rDocument, + SwDocStyleSheetPool& rPool) : + + SfxStyleSheetBase( OUString(), &rPool, SfxStyleFamily::Char, SfxStyleSearchBits::Auto ), + pCharFormat(nullptr), + pColl(nullptr), + pFrameFormat(nullptr), + pDesc(nullptr), + pNumRule(nullptr), + pTableFormat(nullptr), + pBoxFormat(nullptr), + rDoc(rDocument), + 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_AUTO_STYLE_UPDATE, SID_ATTR_AUTO_STYLE_UPDATE, + FN_PARAM_FTN_INFO, FN_PARAM_FTN_INFO, + FN_COND_COLL, FN_COND_COLL>{}), + 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 (!bPhysical) + FillStyleSheet(FillPhysical); + + SwFormat* pFormat = nullptr; + switch (nFamily) + { + case SfxStyleFamily::Char: + pFormat = rDoc.FindCharFormatByName(aName); + if (pFormat) + { + pFormat->SetGrabBagItem(rVal); + bChg = true; + } + break; + case SfxStyleFamily::Para: + pFormat = rDoc.FindTextFormatCollByName(aName); + if (pFormat) + { + pFormat->SetGrabBagItem(rVal); + bChg = true; + } + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = rDoc.FindNumRulePtr(aName); + if (pRule) + { + pRule->SetGrabBagItem(rVal); + bChg = true; + } + } + break; + default: + break; + } + + if (bChg) + { + dynamic_cast(*m_pPool).InvalidateIterator(); + m_pPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *this)); + SwEditShell* pSh = rDoc.GetEditShell(); + if (pSh) + pSh->CallChgLnk(); + } +} + +void SwDocStyleSheet::GetGrabBagItem(uno::Any& rVal) const +{ + SwFormat* pFormat = nullptr; + switch (nFamily) + { + case SfxStyleFamily::Char: + pFormat = rDoc.FindCharFormatByName(aName); + if (pFormat) + pFormat->GetGrabBagItem(rVal); + break; + case SfxStyleFamily::Para: + pFormat = rDoc.FindTextFormatCollByName(aName); + if (pFormat) + pFormat->GetGrabBagItem(rVal); + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = rDoc.FindNumRulePtr(aName); + if (pRule) + pRule->GetGrabBagItem(rVal); + } + break; + default: + break; + } +} +// virtual methods +void SwDocStyleSheet::SetHidden( bool bValue ) +{ + bool bChg = false; + if(!bPhysical) + FillStyleSheet( FillPhysical ); + + SwFormat* pFormat = nullptr; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = rDoc.FindCharFormatByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Para: + pFormat = rDoc.FindTextFormatCollByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Frame: + pFormat = rDoc.FindFrameFormatByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Page: + { + SwPageDesc* pPgDesc = rDoc.FindPageDesc(aName); + if ( pPgDesc ) + { + pPgDesc->SetHidden( bValue ); + bChg = true; + } + } + break; + + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = rDoc.FindNumRulePtr( aName ); + if ( pRule ) + { + pRule->SetHidden( bValue ); + bChg = true; + } + } + break; + + case SfxStyleFamily::Table: + { + SwTableAutoFormat* pTableAutoFormat = 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(*m_pPool).InvalidateIterator(); // internal list has to be updated + m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) ); + SwEditShell* pSh = rDoc.GetEditShell(); + if( pSh ) + pSh->CallChgLnk(); + } +} + +bool SwDocStyleSheet::IsHidden( ) const +{ + bool bRet = false; + + SwFormat* pFormat = nullptr; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = rDoc.FindCharFormatByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Para: + pFormat = rDoc.FindTextFormatCollByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Frame: + pFormat = rDoc.FindFrameFormatByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Page: + { + SwPageDesc* pPgDesc = rDoc.FindPageDesc(aName); + bRet = pPgDesc && pPgDesc->IsHidden( ); + } + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = rDoc.FindNumRulePtr( aName ); + bRet = pRule && pRule->IsHidden( ); + } + break; + case SfxStyleFamily::Table: + { + SwTableAutoFormat* pTableAutoFormat = rDoc.GetTableStyles().FindAutoFormat( aName ); + bRet = pTableAutoFormat && pTableAutoFormat->IsHidden( ); + } + break; + default: + break; + } + + return bRet; +} + +const OUString& SwDocStyleSheet::GetParent() const +{ + if( !bPhysical ) + { + // check if it's already in document + SwFormat* pFormat = nullptr; + SwGetPoolIdFromName eGetType; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = rDoc.FindCharFormatByName( aName ); + eGetType = SwGetPoolIdFromName::ChrFmt; + break; + + case SfxStyleFamily::Para: + pFormat = rDoc.FindTextFormatCollByName( aName ); + eGetType = SwGetPoolIdFromName::TxtColl; + break; + + case SfxStyleFamily::Frame: + pFormat = 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(this); + pThis->aParent = sTmp; + } + return aParent; +} + +// Follower +const OUString& SwDocStyleSheet::GetFollow() const +{ + if( !bPhysical ) + { + SwDocStyleSheet* pThis = const_cast(this); + pThis->FillStyleSheet( FillAllInfo ); + } + return aFollow; +} + +// 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()); + + const OUString sPlus(" + "); + 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; + SvtCJKOptions aCJKOptions; + 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(aCJKOptions.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(aCTLOptions.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)).append(sPlus).append(sModel); + if (sPageNum != "0") + { + aDesc.append(sPlus).append(SwResId(STR_PAGEOFFSET)).append(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(!bPhysical) + FillStyleSheet( FillPhysical ); + + bool bChg = false; + switch(nFamily) + { + case SfxStyleFamily::Char : + { + OSL_ENSURE(pCharFormat, "SwCharFormat missing!"); + if( pCharFormat && pCharFormat->GetName() != rStr ) + { + if (!pCharFormat->GetName().isEmpty()) + rDoc.RenameFormat(*pCharFormat, rStr); + else + pCharFormat->SetName(rStr); + + bChg = true; + } + break; + } + case SfxStyleFamily::Para : + { + OSL_ENSURE(pColl, "Collection missing!"); + if( pColl && pColl->GetName() != rStr ) + { + if (!pColl->GetName().isEmpty()) + rDoc.RenameFormat(*pColl, rStr); + else + pColl->SetName(rStr); + + bChg = true; + } + break; + } + case SfxStyleFamily::Frame: + { + OSL_ENSURE(pFrameFormat, "FrameFormat missing!"); + if( pFrameFormat && pFrameFormat->GetName() != rStr ) + { + if (!pFrameFormat->GetName().isEmpty()) + rDoc.RenameFormat(*pFrameFormat, rStr); + else + pFrameFormat->SetName( rStr ); + + bChg = true; + } + break; + } + case SfxStyleFamily::Page : + OSL_ENSURE(pDesc, "PageDesc missing!"); + if( pDesc && 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(pDesc)); + const OUString aOldName(aPageDesc.GetName()); + + aPageDesc.SetName( rStr ); + bool const bDoesUndo = rDoc.GetIDocumentUndoRedo().DoesUndo(); + + rDoc.GetIDocumentUndoRedo().DoUndo(!aOldName.isEmpty()); + rDoc.ChgPageDesc(aOldName, aPageDesc); + rDoc.GetIDocumentUndoRedo().DoUndo(bDoesUndo); + + rDoc.getIDocumentState().SetModified(); + bChg = true; + } + break; + case SfxStyleFamily::Pseudo: + OSL_ENSURE(pNumRule, "NumRule missing!"); + + if (pNumRule) + { + OUString aOldName = pNumRule->GetName(); + + if (!aOldName.isEmpty()) + { + if ( aOldName != rStr && + rDoc.RenameNumRule(aOldName, rStr)) + { + pNumRule = rDoc.FindNumRulePtr(rStr); + rDoc.getIDocumentState().SetModified(); + + bChg = true; + } + } + else + { + // #i91400# + const_cast(pNumRule)->SetName( rStr, rDoc.getIDocumentListsAccess() ); + 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 ) ); + SwEditShell* pSh = rDoc.GetEditShell(); + if( pSh ) + 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( pCharFormat, "SwCharFormat missing!" ); + if( nullptr != ( pFormat = pCharFormat ) && !rStr.isEmpty() ) + pParent = lcl_FindCharFormat(rDoc, rStr); + break; + + case SfxStyleFamily::Para : + OSL_ENSURE( pColl, "Collection missing!"); + if( nullptr != ( pFormat = pColl ) && !rStr.isEmpty() ) + pParent = lcl_FindParaFormat( rDoc, rStr ); + break; + + case SfxStyleFamily::Frame: + OSL_ENSURE(pFrameFormat, "FrameFormat missing!"); + if( nullptr != ( pFormat = pFrameFormat ) && !rStr.isEmpty() ) + pParent = lcl_FindFrameFormat( 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( 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( rDoc ); + switch(nFamily) + { + case SfxStyleFamily::Para : + { + OSL_ENSURE(pColl, "Collection missing!"); + if( pColl ) + { + SwTextFormatColl* pFollow = pColl; + if( !rStr.isEmpty() && nullptr == (pFollow = lcl_FindParaFormat(rDoc, rStr) )) + pFollow = pColl; + + pColl->SetNextTextFormatColl(*pFollow); + } + break; + } + case SfxStyleFamily::Page : + { + OSL_ENSURE(pDesc, "PageDesc missing!"); + if( pDesc ) + { + const SwPageDesc* pFollowDesc = !rStr.isEmpty() + ? lcl_FindPageDesc(rDoc, rStr) + : nullptr; + size_t nId = 0; + if (pFollowDesc != pDesc->GetFollow() && rDoc.FindPageDesc(pDesc->GetName(), &nId)) + { + SwPageDesc aDesc( *pDesc ); + aDesc.SetFollow( pFollowDesc ); + rDoc.ChgPageDesc( nId, aDesc ); + pDesc = &rDoc.GetPageDesc( nId ); + } + } + break; + } + case SfxStyleFamily::Char: + case SfxStyleFamily::Frame: + case SfxStyleFamily::Pseudo: + break; + default: + OSL_ENSURE(false, "unknown style family"); + } + + return true; +} + +static +std::unique_ptr lcl_SwFormatToFlatItemSet(SwFormat const *const pFormat) +{ + // note: we don't add the odd items that GetItemSet() would add + // because they don't seem relevant for preview + std::vector 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 + std::unique_ptr pRet(new SfxItemSet(*sets.back())); + sets.pop_back(); + for (auto iter = sets.rbegin(); iter != sets.rend(); ++iter) + { // in reverse so child overrides parent + pRet->Put(**iter); + } + return pRet; +} + +std::unique_ptr 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::unique_ptr(); + } + if (!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::unique_ptr pRet; + FillStyleSheet(FillPreview, &pRet); + assert(pRet); + return pRet; + } + else + { + switch (nFamily) + { + case SfxStyleFamily::Char: + return lcl_SwFormatToFlatItemSet(pCharFormat); + case SfxStyleFamily::Para: + return lcl_SwFormatToFlatItemSet(pColl); + case SfxStyleFamily::Frame: + return lcl_SwFormatToFlatItemSet(pFrameFormat); + default: + std::abort(); + } + } +} + +// extract ItemSet to Name and Family, Mask + +SfxItemSet& SwDocStyleSheet::GetItemSet() +{ + if(!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(!pCharFormat, "sw.ui", "Where's SwCharFormat"); + aCoreSet.Put(pCharFormat->GetAttrSet()); + aCoreSet.Put( aBoxInfo ); + + if(pCharFormat->DerivedFrom()) + aCoreSet.SetParent(&pCharFormat->DerivedFrom()->GetAttrSet()); + } + else if ( nFamily == SfxStyleFamily::Para ) + { + OSL_ENSURE(pColl, "Where's Collection"); + aCoreSet.Put(pColl->GetAttrSet()); + aCoreSet.Put( aBoxInfo ); + aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, pColl->IsAutoUpdateFormat())); + + if(pColl->DerivedFrom()) + aCoreSet.SetParent(&pColl->DerivedFrom()->GetAttrSet()); + } + else + { + OSL_ENSURE(pFrameFormat, "Where's FrameFormat"); + aCoreSet.Put(pFrameFormat->GetAttrSet()); + aCoreSet.Put( aBoxInfo ); + aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, pFrameFormat->IsAutoUpdateFormat())); + + if(pFrameFormat->DerivedFrom()) + aCoreSet.SetParent(&pFrameFormat->DerivedFrom()->GetAttrSet()); + + // create needed items for XPropertyList entries from the DrawModel so that + // the Area TabPage can access them + const SwDrawModel* pDrawModel = rDoc.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)); + } + } + break; + + case SfxStyleFamily::Page : + { + // set correct parent to get the drawing::FillStyle_NONE FillStyle as needed + if(!aCoreSet.GetParent()) + { + aCoreSet.SetParent(&rDoc.GetDfltFrameFormat()->GetAttrSet()); + } + + OSL_ENSURE(pDesc, "No PageDescriptor"); + ::PageDescToItemSet(*const_cast(pDesc), aCoreSet); + } + break; + + case SfxStyleFamily::Pseudo: + { + OSL_ENSURE(pNumRule, "No NumRule"); + SvxNumRule aRule = pNumRule->MakeSvxNumRule(); + aCoreSet.Put(SvxNumBulletItem(aRule)); + } + break; + + default: + OSL_ENSURE(false, "unknown style family"); + } + // Member of Baseclass + pSet = &aCoreSet; + + return aCoreSet; +} + +void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet ) +{ + if ( nFamily != SfxStyleFamily::Para ) + { + return; + } + + OSL_ENSURE( pColl, " - missing paragraph style"); + if ( pColl->AreListLevelIndentsApplicable() ) + { + OSL_ENSURE( pColl->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET, + " - list level indents are applicable at paragraph style, but no list style found. Serious defect." ); + const OUString sNumRule = pColl->GetNumRule().GetValue(); + if (!sNumRule.isEmpty()) + { + const SwNumRule* pRule = rDoc.FindNumRulePtr( sNumRule ); + if( pRule ) + { + const SwNumFormat& rFormat = pRule->Get( 0 ); + if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) + { + SvxLRSpaceItem aLR( RES_LR_SPACE ); + aLR.SetTextLeft( rFormat.GetIndentAt() ); + aLR.SetTextFirstLineOffset( static_cast(rFormat.GetFirstLineIndent()) ); + rSet.Put( aLR ); + } + } + } + } +} + +// handling of parameter +void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, + const bool bResetIndentAttrsAtParagraphStyle ) +{ + // if applicable determine format first + if(!bPhysical) + FillStyleSheet( FillPhysical ); + + SwImplShellAction aTmpSh( rDoc ); + + OSL_ENSURE( &rSet != &aCoreSet, "SetItemSet with own Set is not allowed" ); + + if (rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + SwRewriter aRewriter; + aRewriter.AddRule( UndoArg1, GetName() ); + rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::INSFMTATTR, &aRewriter ); + } + + SwFormat* pFormat = nullptr; + std::unique_ptr pNewDsc; + size_t nPgDscPos = 0; + + switch(nFamily) + { + case SfxStyleFamily::Char : + { + OSL_ENSURE(pCharFormat, "Where's CharFormat"); + pFormat = pCharFormat; + } + break; + + case SfxStyleFamily::Para : + { + OSL_ENSURE(pColl, "Where's Collection"); + const SfxPoolItem* pAutoUpdate; + if(SfxItemState::SET == rSet.GetItemState(SID_ATTR_AUTO_STYLE_UPDATE,false, &pAutoUpdate )) + { + pColl->SetAutoUpdateFormat(static_cast(pAutoUpdate)->GetValue()); + } + + const SwCondCollItem* pCondItem; + if( SfxItemState::SET != rSet.GetItemState( FN_COND_COLL, false, + reinterpret_cast(&pCondItem) )) + pCondItem = nullptr; + + if( RES_CONDTXTFMTCOLL == 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(pColl)->RemoveCondition( aCond ); + const OUString sStyle = pCondItem->GetStyle( i ); + if (sStyle.isEmpty()) + continue; + SwFormat *const pFindFormat = lcl_FindParaFormat( rDoc, sStyle ); + if (pFindFormat) + { + aCond.RegisterToFormat( *pFindFormat ); + static_cast(pColl)->InsertCondition( aCond ); + } + } + + // Update document to new conditions + SwCondCollCondChg aMsg( pColl ); + pColl->ModifyNotification( &aMsg, &aMsg ); + } + else if( pCondItem && !pColl->HasWriterListeners() ) + { + // no conditional template, then first create and adopt + // all important values + SwConditionTextFormatColl* pCColl = rDoc.MakeCondTextFormatColl( + pColl->GetName(), static_cast(pColl->DerivedFrom()) ); + if( pColl != &pColl->GetNextTextFormatColl() ) + pCColl->SetNextTextFormatColl( pColl->GetNextTextFormatColl() ); + + if( pColl->IsAssignedToListLevelOfOutlineStyle()) + pCColl->AssignToListLevelOfOutlineStyle(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( rDoc, sStyle ); + if (pFindFormat) + { + pCColl->InsertCondition( SwCollCondition( pFindFormat, + pCmds[ i ].nCnd, pCmds[ i ].nSubCond ) ); + } + } + + rDoc.DelTextFormatColl( pColl ); + pColl = pCColl; + } + if ( bResetIndentAttrsAtParagraphStyle && + rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET && + rSet.GetItemState( RES_LR_SPACE, false ) != SfxItemState::SET && + pColl->GetItemState( RES_LR_SPACE, false ) == SfxItemState::SET ) + { + rDoc.ResetAttrAtFormat( RES_LR_SPACE, *pColl ); + } + + // #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. + const SfxPoolItem* pNumRuleItem = nullptr; + if( SfxItemState::SET == rSet.GetItemState( RES_PARATR_NUMRULE, false, &pNumRuleItem ) ) + { // Setting a numbering rule? + const OUString sNumRule = static_cast(pNumRuleItem)->GetValue(); + if (!sNumRule.isEmpty()) + { + SwNumRule* pRule = 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 + { + rDoc.getIDocumentStylePoolAccess().GetNumRuleFromPool( nPoolId ); // Create numbering rule (physical) + } + } + } + } + + pFormat = pColl; + + sal_uInt16 nId = pColl->GetPoolFormatId() & + ~ ( COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID ); + switch( GetMask() & ( static_cast(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; + } + pColl->SetPoolFormatId( nId ); + break; + } + case SfxStyleFamily::Frame: + { + OSL_ENSURE(pFrameFormat, "Where's FrameFormat"); + const SfxPoolItem* pAutoUpdate; + if(SfxItemState::SET == rSet.GetItemState(SID_ATTR_AUTO_STYLE_UPDATE,false, &pAutoUpdate )) + { + pFrameFormat->SetAutoUpdateFormat(static_cast(pAutoUpdate)->GetValue()); + } + pFormat = pFrameFormat; + } + break; + + case SfxStyleFamily::Page : + { + OSL_ENSURE(pDesc, "Where's PageDescriptor"); + + if (rDoc.FindPageDesc(pDesc->GetName(), &nPgDscPos)) + { + pNewDsc.reset( new SwPageDesc( *pDesc ) ); + // #i48949# - no undo actions for the + // copy of the page style + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + rDoc.CopyPageDesc(*pDesc, *pNewDsc); // #i7983# + + pFormat = &pNewDsc->GetMaster(); + } + } + break; + + case SfxStyleFamily::Pseudo: + { + OSL_ENSURE(pNumRule, "Where's NumRule"); + + if (!pNumRule) + break; + + const SfxPoolItem* pItem; + switch( rSet.GetItemState( SID_ATTR_NUMBERING_RULE, false, &pItem )) + { + case SfxItemState::SET: + { + SvxNumRule* pSetRule = static_cast(pItem)->GetNumRule(); + pSetRule->UnLinkGraphics(); + SwNumRule aSetRule(*pNumRule); + aSetRule.SetSvxRule(*pSetRule, &rDoc); + rDoc.ChgNumRuleFormats( aSetRule ); + } + break; + case SfxItemState::DONTCARE: + // set NumRule to default values + // what are the default values? + { + SwNumRule aRule( pNumRule->GetName(), + // #i89178# + numfunc::GetDefaultPositionAndSpaceMode() ); + 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 in order to + // create an Undo object for the attribute reset. + rDoc.ResetAttrAtFormat( rSet.GetWhichByPos(aIter.GetCurPos()), + *pFormat ); + } + + pItem = aIter.NextItem(); + } while (pItem); + 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 + rDoc.CheckForUniqueItemForLineFillNameOrIndex(aSet); + } + + aCoreSet.ClearItem(); + + if( pNewDsc ) + { + ::ItemSetToPageDesc( aSet, *pNewDsc ); + rDoc.ChgPageDesc( nPgDscPos, *pNewDsc ); + pDesc = &rDoc.GetPageDesc( nPgDscPos ); + rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983# + pNewDsc.reset(); + } + else + rDoc.ChgFormat(*pFormat, aSet); // put all that is set + } + else + { + aCoreSet.ClearItem(); + if( pNewDsc ) // we still need to delete it + { + rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983# + pNewDsc.reset(); + } + } + + if (rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr); + } +} + +static void lcl_SaveStyles( SfxStyleFamily nFamily, std::vector& rArr, SwDoc& rDoc ) +{ + switch( nFamily ) + { + case SfxStyleFamily::Char: + { + const SwCharFormats& rTable = *rDoc.GetCharFormats(); + for( size_t n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + rArr.push_back( rTable[ n ] ); + } + } + break; + case SfxStyleFamily::Para: + { + const SwTextFormatColls& rTable = *rDoc.GetTextFormatColls(); + for( size_t n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + rArr.push_back( rTable[ n ] ); + } + } + break; + case SfxStyleFamily::Frame: + { + const SwFrameFormats& rTable = *rDoc.GetFrameFormats(); + for( size_t n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + rArr.push_back( rTable[ n ] ); + } + } + 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( size_t n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + rArr.push_back( rTable[ n ] ); + } + } + break; + default: break; + } +} + +static bool lcl_Contains(const std::vector& rArr, const void* p) +{ + return std::find( rArr.begin(), rArr.end(), p ) != rArr.end(); +} + +static void lcl_DeleteInfoStyles( SfxStyleFamily nFamily, std::vector const & rArr, SwDoc& rDoc ) +{ + size_t n, nCnt; + switch( nFamily ) + { + case SfxStyleFamily::Char: + { + std::deque 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( n = 0, nCnt = aDelArr.size(); n < nCnt; ++n ) + rDoc.DelCharFormat( aDelArr[ n ] ); + } + break; + + case SfxStyleFamily::Para : + { + std::deque 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( n = 0, nCnt = aDelArr.size(); n < nCnt; ++n ) + rDoc.DelTextFormatColl( aDelArr[ n ] ); + } + break; + + case SfxStyleFamily::Frame: + { + std::deque aDelArr; + const SwFrameFormats& rTable = *rDoc.GetFrameFormats(); + for( n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, rTable[ n ] )) + aDelArr.push_front( rTable[ n ] ); + } + for( n = 0, nCnt = aDelArr.size(); n < nCnt; ++n ) + rDoc.DelFrameFormat( aDelArr[ n ] ); + } + break; + + case SfxStyleFamily::Page: + { + std::deque aDelArr; + for( n = 0, nCnt = rDoc.GetPageDescCnt(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, &rDoc.GetPageDesc( n ) )) + aDelArr.push_front( n ); + } + for( n = 0, nCnt = aDelArr.size(); n < nCnt; ++n ) + rDoc.DelPageDesc( aDelArr[ n ] ); + } + break; + + case SfxStyleFamily::Pseudo: + { + std::deque aDelArr; + const SwNumRuleTable& rTable = rDoc.GetNumRuleTable(); + for( n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, rTable[ n ] )) + aDelArr.push_front( rTable[ n ] ); + } + for( n = 0, nCnt = aDelArr.size(); n < nCnt; ++n ) + rDoc.DelNumRule( aDelArr[ n ]->GetName() ); + } + break; + default: break; + } +} + +// determine the format +bool SwDocStyleSheet::FillStyleSheet( + FillStyleType const eFType, std::unique_ptr *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 aDelArr; + bool const isModified(rDoc.getIDocumentState().IsModified()); + + switch(nFamily) + { + case SfxStyleFamily::Char: + pCharFormat = lcl_FindCharFormat(rDoc, aName, this, bCreate ); + bPhysical = nullptr != pCharFormat; + if( bFillOnlyInfo && !bPhysical ) + { + // create style (plus all needed parents) and clean it up + // later - without affecting the undo/redo stack + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, rDoc ); + pCharFormat = lcl_FindCharFormat(rDoc, aName, this ); + } + + pFormat = pCharFormat; + if( !bCreate && !pFormat ) + { + if( aName == SwResId(STR_POOLCHR_STANDARD)) + nPoolId = 0; + else + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt ); + } + + bRet = nullptr != pCharFormat || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + pCharFormat = nullptr; + break; + + case SfxStyleFamily::Para: + { + pColl = lcl_FindParaFormat(rDoc, aName, this, bCreate); + bPhysical = nullptr != pColl; + if( bFillOnlyInfo && !bPhysical ) + { + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, rDoc ); + pColl = lcl_FindParaFormat(rDoc, aName, this ); + } + + pFormat = pColl; + if( pColl ) + PresetFollow( pColl->GetNextTextFormatColl().GetName() ); + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl ); + + bRet = nullptr != pColl || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + pColl = nullptr; + } + break; + + case SfxStyleFamily::Frame: + pFrameFormat = lcl_FindFrameFormat(rDoc, aName, this, bCreate); + bPhysical = nullptr != pFrameFormat; + if (bFillOnlyInfo && !bPhysical) + { + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, rDoc ); + pFrameFormat = lcl_FindFrameFormat(rDoc, aName, this ); + } + pFormat = pFrameFormat; + if( !bCreate && !pFormat ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt ); + + bRet = nullptr != pFrameFormat || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + pFrameFormat = nullptr; + break; + + case SfxStyleFamily::Page: + pDesc = lcl_FindPageDesc(rDoc, aName, this, bCreate); + bPhysical = nullptr != pDesc; + if( bFillOnlyInfo && !pDesc ) + { + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, rDoc ); + pDesc = lcl_FindPageDesc( rDoc, aName, this ); + } + + if( pDesc ) + { + nPoolId = pDesc->GetPoolFormatId(); + nHelpId = pDesc->GetPoolHelpId(); + if( pDesc->GetPoolHlpFileId() != UCHAR_MAX ) + aHelpFile = *rDoc.GetDocPattern( pDesc->GetPoolHlpFileId() ); + else + aHelpFile.clear(); + } + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc ); + SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto ); + + bRet = nullptr != pDesc || USHRT_MAX != nPoolId; + if( bDeleteInfo ) + pDesc = nullptr; + break; + + case SfxStyleFamily::Pseudo: + pNumRule = lcl_FindNumRule(rDoc, aName, this, bCreate); + bPhysical = nullptr != pNumRule; + if( bFillOnlyInfo && !pNumRule ) + { + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, rDoc ); + pNumRule = lcl_FindNumRule( rDoc, aName, this ); + } + + if( pNumRule ) + { + nPoolId = pNumRule->GetPoolFormatId(); + nHelpId = pNumRule->GetPoolHelpId(); + if( pNumRule->GetPoolHlpFileId() != UCHAR_MAX ) + aHelpFile = *rDoc.GetDocPattern( pNumRule->GetPoolHlpFileId() ); + else + aHelpFile.clear(); + } + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule ); + SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto ); + + bRet = nullptr != pNumRule || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + pNumRule = nullptr; + break; + + case SfxStyleFamily::Table: + pTableFormat = lcl_FindTableStyle(rDoc, aName, this, bCreate); + SetMask((pTableFormat && pTableFormat->IsUserDefined()) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto); + bRet = bPhysical = (nullptr != pTableFormat); + break; + + case SfxStyleFamily::Cell: + pBoxFormat = lcl_FindCellStyle(rDoc, aName, this); + bRet = bPhysical = (nullptr != 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 == 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( bPhysical, "Format not found" ); + + nHelpId = pFormat->GetPoolHelpId(); + if( pFormat->GetPoolHlpFileId() != UCHAR_MAX ) + aHelpFile = *rDoc.GetDocPattern( pFormat->GetPoolHlpFileId() ); + else + aHelpFile.clear(); + + if( RES_CONDTXTFMTCOLL == pFormat->Which() ) + _nMask |= SfxStyleSearchBits::SwCondColl; + + if (FillPreview == eFType) + { + assert(o_ppFlatSet); + *o_ppFlatSet = lcl_SwFormatToFlatItemSet(pFormat); + } + } + + SetMask( _nMask ); + } + if( bDeleteInfo && bFillOnlyInfo ) + { + ::sw::UndoGuard const ug(rDoc.GetIDocumentUndoRedo()); + ::lcl_DeleteInfoStyles( nFamily, aDelArr, rDoc ); + if (!isModified) + { + rDoc.getIDocumentState().ResetModified(); + } + } + return bRet; +} + +// Create new format in Core +void SwDocStyleSheet::Create() +{ + switch(nFamily) + { + case SfxStyleFamily::Char : + pCharFormat = lcl_FindCharFormat( rDoc, aName ); + if( !pCharFormat ) + pCharFormat = rDoc.MakeCharFormat(aName, + rDoc.GetDfltCharFormat()); + pCharFormat->SetAuto(false); + break; + + case SfxStyleFamily::Para : + pColl = lcl_FindParaFormat( rDoc, aName ); + if( !pColl ) + { + SwTextFormatColl *pPar = (*rDoc.GetTextFormatColls())[0]; + if( nMask & SfxStyleSearchBits::SwCondColl ) + pColl = rDoc.MakeCondTextFormatColl( aName, pPar ); + else + pColl = rDoc.MakeTextFormatColl( aName, pPar ); + } + break; + + case SfxStyleFamily::Frame: + pFrameFormat = lcl_FindFrameFormat( rDoc, aName ); + if( !pFrameFormat ) + pFrameFormat = rDoc.MakeFrameFormat(aName, rDoc.GetDfltFrameFormat(), false, false); + + break; + + case SfxStyleFamily::Page : + pDesc = lcl_FindPageDesc( rDoc, aName ); + if( !pDesc ) + { + pDesc = rDoc.MakePageDesc(aName); + } + break; + + case SfxStyleFamily::Pseudo: + pNumRule = lcl_FindNumRule( rDoc, aName ); + if( !pNumRule ) + { + const OUString sTmpNm( aName.isEmpty() ? rDoc.GetUniqueNumRuleName() : aName ); + SwNumRule* pRule = rDoc.GetNumRuleTable()[ + rDoc.MakeNumRule( sTmpNm, nullptr, false, + // #i89178# + numfunc::GetDefaultPositionAndSpaceMode() ) ]; + pRule->SetAutoRule( false ); + if( aName.isEmpty() ) + { + // #i91400# + pRule->SetName( aName, rDoc.getIDocumentListsAccess() ); + } + pNumRule = pRule; + } + break; + + case SfxStyleFamily::Table: + if (aName.isEmpty()) + return; + pTableFormat = lcl_FindTableStyle(rDoc, aName); + if (!pTableFormat) + { + rDoc.MakeTableStyle(aName); + pTableFormat = rDoc.GetTableStyles().FindAutoFormat(aName); + SAL_WARN_IF(!pTableFormat, "sw.ui", "Recently added auto format not found"); + } + break; + default:; //prevent warning + } + bPhysical = true; + aCoreSet.ClearItem(); +} + +SwCharFormat* SwDocStyleSheet::GetCharFormat() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + return pCharFormat; +} + +SwTextFormatColl* SwDocStyleSheet::GetCollection() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + return pColl; +} + +const SwPageDesc* SwDocStyleSheet::GetPageDesc() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + return pDesc; +} + +const SwNumRule * SwDocStyleSheet::GetNumRule() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + return pNumRule; +} + + +void SwDocStyleSheet::SetNumRule(const SwNumRule& rRule) +{ + OSL_ENSURE(pNumRule, "Where is the NumRule"); + rDoc.ChgNumRuleFormats( rRule ); +} + +SwTableAutoFormat* SwDocStyleSheet::GetTableFormat() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + assert(pTableFormat && "SwDocStyleSheet table style, SwTableAutoFormat not found"); + return pTableFormat; +} + +// re-generate Name AND Family from String +// First() and Next() (see below) insert an identification letter at Pos.1 + +void SwDocStyleSheet::PresetNameAndFamily(const OUString& rName) +{ + switch( rName[0] ) + { + case cPARA: nFamily = SfxStyleFamily::Para; break; + case cFRAME: nFamily = SfxStyleFamily::Frame; break; + case cPAGE: nFamily = SfxStyleFamily::Page; break; + case cNUMRULE: nFamily = SfxStyleFamily::Pseudo; break; + case cTABSTYLE: nFamily = SfxStyleFamily::Table; break; + default: nFamily = SfxStyleFamily::Char; break; + } + aName = rName.copy(1); +} + +// Is the format physically present yet +void SwDocStyleSheet::SetPhysical(bool bPhys) +{ + bPhysical = bPhys; + + if(!bPhys) + { + pCharFormat = nullptr; + pColl = nullptr; + pFrameFormat = nullptr; + pDesc = nullptr; + } +} + +SwFrameFormat* SwDocStyleSheet::GetFrameFormat() +{ + if(!bPhysical) + FillStyleSheet( FillPhysical ); + return pFrameFormat; +} + +bool SwDocStyleSheet::IsUsed() const +{ + if( !bPhysical ) + { + SwDocStyleSheet* pThis = const_cast(this); + pThis->FillStyleSheet( FillOnlyName ); + } + + if( !bPhysical ) + return false; + + const SwModify* pMod; + switch( nFamily ) + { + case SfxStyleFamily::Char : pMod = pCharFormat; break; + case SfxStyleFamily::Para : pMod = pColl; break; + case SfxStyleFamily::Frame: pMod = pFrameFormat; break; + case SfxStyleFamily::Page : pMod = pDesc; break; + + case SfxStyleFamily::Pseudo: + return pNumRule && SwDoc::IsUsed( *pNumRule ); + + case SfxStyleFamily::Table: + return pTableFormat && rDoc.IsUsed( *pTableFormat ); + + default: + OSL_ENSURE(false, "unknown style family"); + return false; + } + return rDoc.IsUsed( *pMod ); +} + +OUString SwDocStyleSheet::GetUsedBy() +{ + return pNumRule ? 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( !pCharFormat && + nullptr == (pCharFormat = lcl_FindCharFormat( rDoc, aName, nullptr, false )) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = pCharFormat; + break; + + case SfxStyleFamily::Para: + if( !pColl && + nullptr == ( pColl = lcl_FindParaFormat( rDoc, aName, nullptr, false )) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = pColl; + break; + + case SfxStyleFamily::Frame: + if( !pFrameFormat && + nullptr == ( pFrameFormat = lcl_FindFrameFormat( rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = pFrameFormat; + break; + + case SfxStyleFamily::Page: + if( !pDesc && + nullptr == ( pDesc = lcl_FindPageDesc( rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc ); + return USHRT_MAX == nId ? 0 : nId; + } + + nId = pDesc->GetPoolHelpId(); + nFileId = pDesc->GetPoolHlpFileId(); + nPoolId = pDesc->GetPoolFormatId(); + break; + + case SfxStyleFamily::Pseudo: + if( !pNumRule && + nullptr == ( pNumRule = lcl_FindNumRule( rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule ); + return USHRT_MAX == nId ? 0 : nId; + } + + nId = pNumRule->GetPoolHelpId(); + nFileId = pNumRule->GetPoolHlpFileId(); + nPoolId = 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 = 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 >(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 = pCharFormat; break; + case SfxStyleFamily::Para : pTmpFormat = pColl; break; + case SfxStyleFamily::Frame: pTmpFormat = pFrameFormat; break; + case SfxStyleFamily::Page : + const_cast(pDesc)->SetPoolHelpId( nHId ); + const_cast(pDesc)->SetPoolHlpFileId( nFileId ); + break; + + case SfxStyleFamily::Pseudo: + const_cast(pNumRule)->SetPoolHelpId( nHId ); + const_cast(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)) + , rDoc(rDocument) +{ + 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; +} + +SfxStyleSheetBase* SwDocStyleSheetPool::Create( const SfxStyleSheetBase& /*rOrg*/) +{ + OSL_ENSURE(false , "Create in SW-Stylesheet-Pool not possible" ); + return nullptr; +} + +SfxStyleSheetBase* SwDocStyleSheetPool::Create( const OUString &, + SfxStyleFamily, SfxStyleSearchBits ) +{ + OSL_ENSURE( false, "Create in SW-Stylesheet-Pool not possible" ); + return nullptr; +} + +std::unique_ptr SwDocStyleSheetPool::CreateIterator( SfxStyleFamily eFam, SfxStyleSearchBits _nMask ) +{ + return std::make_unique(*this, eFam, _nMask); +} + +void SwDocStyleSheetPool::dispose() +{ + mxStyleSheet.clear(); +} + +void SwDocStyleSheetPool::Remove( SfxStyleSheetBase* pStyle) +{ + if( !pStyle ) + return; + + bool bBroadcast = true; + SwImplShellAction aTmpSh( rDoc ); + const OUString sName = pStyle->GetName(); + switch( pStyle->GetFamily() ) + { + case SfxStyleFamily::Char: + { + SwCharFormat* pFormat = lcl_FindCharFormat(rDoc, sName, nullptr, false ); + if(pFormat) + rDoc.DelCharFormat(pFormat); + } + break; + case SfxStyleFamily::Para: + { + SwTextFormatColl* pColl = lcl_FindParaFormat(rDoc, sName, nullptr, false ); + if(pColl) + rDoc.DelTextFormatColl(pColl); + } + break; + case SfxStyleFamily::Frame: + { + SwFrameFormat* pFormat = lcl_FindFrameFormat(rDoc, sName, nullptr, false ); + if(pFormat) + rDoc.DelFrameFormat(pFormat); + } + break; + case SfxStyleFamily::Page : + { + rDoc.DelPageDesc(sName); + } + break; + + case SfxStyleFamily::Pseudo: + { + if( !rDoc.DelNumRule( sName ) ) + // Only send Broadcast, when something was deleted + bBroadcast = false; + } + break; + + case SfxStyleFamily::Table: + { + rDoc.DelTableStyle(sName); + } + break; + + default: + OSL_ENSURE(false, "unknown style family"); + bBroadcast = false; + } + + if( bBroadcast ) + Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetErased, *pStyle ) ); +} + +bool SwDocStyleSheetPool::SetParent( SfxStyleFamily eFam, + const OUString &rStyle, const OUString &rParent ) +{ + SwFormat* pFormat = nullptr, *pParent = nullptr; + switch( eFam ) + { + case SfxStyleFamily::Char : + if( nullptr != ( pFormat = lcl_FindCharFormat( rDoc, rStyle ) ) && !rParent.isEmpty() ) + pParent = lcl_FindCharFormat(rDoc, rParent ); + break; + + case SfxStyleFamily::Para : + if( nullptr != ( pFormat = lcl_FindParaFormat( rDoc, rStyle ) ) && !rParent.isEmpty() ) + pParent = lcl_FindParaFormat( rDoc, rParent ); + break; + + case SfxStyleFamily::Frame: + if( nullptr != ( pFormat = lcl_FindFrameFormat( rDoc, rStyle ) ) && !rParent.isEmpty() ) + pParent = lcl_FindFrameFormat( rDoc, rParent ); + 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() != rParent ) + { + { + SwImplShellAction aTmpSh( rDoc ); + bRet = pFormat->SetDerivedFrom( pParent ); + } + + if( bRet ) + { + // only for Broadcasting + mxStyleSheet->PresetName( rStyle ); + mxStyleSheet->PresetParent( rParent ); + if( SfxStyleFamily::Para == eFam ) + mxStyleSheet->PresetFollow( static_cast(pFormat)-> + GetNextTextFormatColl().GetName() ); + else + mxStyleSheet->PresetFollow( OUString() ); + + Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *mxStyleSheet ) ); + } + } + + return bRet; +} + +SfxStyleSheetBase* SwDocStyleSheetPool::Find( const OUString& rName, + SfxStyleFamily eFam, SfxStyleSearchBits n ) +{ + SfxStyleSearchBits nSMask = n; + if( SfxStyleFamily::Para == eFam && 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 SwModify* 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(pMod)->GetPoolFormatId() + : static_cast(pMod)->GetPoolFormatId(); + + if( ( nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(nId & USER_FMT) + // searched for used and found none + : bSearchUsed ) + 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)) +{ + bFirstCalled = false; + nLastPos = 0; + StartListening(rBase); +} + +SwStyleSheetIterator::~SwStyleSheetIterator() +{ + EndListening( *mxIterSheet->GetPool() ); +} + +sal_uInt16 SwStyleSheetIterator::Count() +{ + // let the list fill correctly!! + if( !bFirstCalled ) + First(); + return aLst.size(); +} + +SfxStyleSheetBase* SwStyleSheetIterator::operator[]( sal_uInt16 nIdx ) +{ + // found + if( !bFirstCalled ) + First(); + mxStyleSheet->PresetNameAndFamily( aLst[ nIdx ] ); + mxStyleSheet->SetPhysical( false ); + mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName ); + + return mxStyleSheet.get(); +} + +SfxStyleSheetBase* SwStyleSheetIterator::First() +{ + // Delete old list + bFirstCalled = true; + nLastPos = 0; + aLst.clear(); + + // Delete current + mxIterSheet->Reset(); + + SwDoc& rDoc = static_cast(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(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; + } + + aLst.Append( cCHAR, 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, cCHAR); + else + { + aLst.Append( cCHAR, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_INET_NORMAL - RES_POOLCHR_BEGIN ] ); + aLst.Append( cCHAR, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_INET_VISIT - RES_POOLCHR_BEGIN ] ); + aLst.Append( cCHAR, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_ENDNOTE - RES_POOLCHR_BEGIN ] ); + aLst.Append( cCHAR, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_FOOTNOTE - RES_POOLCHR_BEGIN ] ); + } + AppendStyleList(SwStyleNameMapper::GetHTMLChrFormatUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, + SwGetPoolIdFromName::ChrFmt, cCHAR); + } + } + + 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); + 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_SENDADRESS: // --> 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; + } + } + aLst.Append( cPARA, pColl->GetName() ); + } + + bAll = ( nSMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwText ) + AppendStyleList(SwStyleNameMapper::GetTextUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, cPARA ); + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwChapter ) + AppendStyleList(SwStyleNameMapper::GetDocUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, cPARA ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwList ) + AppendStyleList(SwStyleNameMapper::GetListsUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, cPARA ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwIndex ) + AppendStyleList(SwStyleNameMapper::GetRegisterUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, cPARA ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwExtra ) + AppendStyleList(SwStyleNameMapper::GetExtraUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, cPARA ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwCondColl ) + { + if( !bIsSearchUsed || + rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( RES_POOLCOLL_TEXT )) + aLst.Append( cPARA, 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, cPARA ) ; + if( !bAll ) + { + // then also the ones, that we are mapping: + static sal_uInt16 aPoolIds[] = { + RES_POOLCOLL_SENDADRESS, // --> 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 ); + aLst.Append( cPARA, 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; + } + } + + aLst.Append( cFRAME, pFormat->GetName() ); + } + + // PoolFormat + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetFrameFormatUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::FrmFmt, cFRAME); + } + + 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; + + aLst.Append( cPAGE, rDesc.GetName() ); + } + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetPageDescUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::PageDesc, cPAGE); + } + + if( nSearchFamily == SfxStyleFamily::Pseudo || + nSearchFamily == SfxStyleFamily::All ) + { + const SwNumRuleTable& rNumTable = rDoc.GetNumRuleTable(); + for(size_t i = 0; i < rNumTable.size(); ++i) + { + const SwNumRule& rRule = *rNumTable[ i ]; + if( !rRule.IsAutoRule() ) + { + if ( nSrchMask == SfxStyleSearchBits::Hidden && !rRule.IsHidden( ) ) + continue; + + bool bUsed = bIsSearchUsed && ( bOrganizer || SwDoc::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; + } + + aLst.Append( cNUMRULE, rRule.GetName() ); + } + } + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetNumRuleUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::NumRule, cNUMRULE); + } + + 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; + } + + aLst.Append( cTABSTYLE, 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); + aLst.Append( cCELLSTYLE, sBoxFormatName ); + } + } + } + const SwCellStyleTable& rCellStyles = rDoc.GetCellStyles(); + for(size_t i = 0; i < rCellStyles.size(); ++i) + aLst.Append( cCELLSTYLE, rCellStyles[i].GetName() ); + } + + if(!aLst.empty()) + { + nLastPos = SAL_MAX_UINT32; + return Next(); + } + return nullptr; +} + +SfxStyleSheetBase* SwStyleSheetIterator::Next() +{ + assert(bFirstCalled); + ++nLastPos; + if(nLastPos < aLst.size()) + { + mxIterSheet->PresetNameAndFamily(aLst[nLastPos]); + 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( !bFirstCalled ) + First(); + + nLastPos = aLst.FindName( nSearchFamily, rName ); + if( SAL_MAX_UINT32 != nLastPos ) + { + // found + mxStyleSheet->PresetNameAndFamily(aLst[nLastPos]); + // 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& rList, + bool bTestUsed, bool bTestHidden, bool bOnlyHidden, + SwGetPoolIdFromName nSection, char cType ) +{ + SwDoc& rDoc = static_cast(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 && SwDoc::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 ) ) + aLst.Append( cType, i ); + } +} + +void SwDocStyleSheetPool::InvalidateIterator() +{ + if (SfxStyleSheetIterator* pIter = GetCachedIterator()) + dynamic_cast(*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? + bFirstCalled = false; + nLastPos = 0; + aLst.clear(); +} + +void SwStyleSheetIterator::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // search and remove from View-List!! + const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast(&rHint); + if( pStyleSheetHint && + SfxHintId::StyleSheetErased == pStyleSheetHint->GetId() ) + { + SfxStyleSheetBase* pStyle = pStyleSheetHint->GetStyleSheet(); + + if (pStyle) + 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 000000000..9a01a8437 --- /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 +#include +#include +#include +#include + +class SwDocShell; + +namespace { + +struct SwProgress +{ + long nStartValue, + nStartCount; + SwDocShell *pDocShell; + std::unique_ptr pProgress; +}; + +} + +static std::vector> *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( const char* pMessResId, long nStartValue, long nEndValue, + SwDocShell *pDocShell ) +{ + if( SW_MOD()->IsEmbeddedLoadSave() ) + return; + + SwProgress *pProgress = nullptr; + + if ( !pProgressContainer ) + pProgressContainer = new std::vector>; + 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(pProgress) ); + } + pProgress->nStartValue = nStartValue; +} + +void SetProgressState( 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() ) + { + SwProgress *pProgress = nullptr; + std::vector::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 000000000..090480bc5 --- /dev/null +++ b/sw/source/uibase/app/swdll.cxx @@ -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 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#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 + { + public: + SwDLLInstance() : comphelper::unique_disposing_solar_mutex_reset_ptr(uno::Reference( frame::Desktop::create(comphelper::getProcessComponentContext()), uno::UNO_QUERY_THROW), new SwDLL, true) + { + } + }; + + struct theSwDLLInstance : public rtl::Static {}; +} + +namespace SwGlobals +{ + void ensure() + { + // coverity[side_effect_free : FALSE] - not actually side-effect-free + theSwDLLInstance::get(); + } + + sw::Filters & getFilters() + { + return theSwDLLInstance::get()->getFilters(); + } +} + +SwDLL::SwDLL() + : m_pAutoCorrCfg(nullptr) +{ + if ( SfxApplication::GetModule(SfxToolsModule::Writer) ) // Module already active + return; + + std::unique_ptr 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(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(); + filters_.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(); + filters_.reset(); + ::FinitCore(); + // sign out object-Factory + SdrObjFactory::RemoveMakeObjectHdl(LINK(&aSwObjectFactory, SwObjectFactory, MakeObject )); +} + +sw::Filters & SwDLL::getFilters() +{ + assert(filters_); + return *filters_; +} + +#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 000000000..bcbcaf005 --- /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/. + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_APP_SWDLLIMPL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_APP_SWDLLIMPL_HXX + +#include + +#include + +#include + +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 > filters_; + SvxAutoCorrCfg *m_pAutoCorrCfg; +}; + +#endif + +/* 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 000000000..b6cfe847a --- /dev/null +++ b/sw/source/uibase/app/swmodul1.cxx @@ -0,0 +1,692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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() +{ + SwView *pActive = ::GetActiveView(); + if( pActive ) + return &pActive->GetWrtShell(); + return nullptr; +} + +SwView* GetActiveView() +{ + SfxViewShell* pView = SfxViewShell::Current(); + return dynamic_cast( pView ); +} + +SwView* SwModule::GetFirstView() +{ + // returns only visible SwView + SwView* pView = static_cast(SfxViewShell::GetFirst(true, checkSfxViewShell)); + return pView; +} + +SwView* SwModule::GetNextView(SwView const * pView) +{ + OSL_ENSURE( pView,"return no SwView" ); + SwView* pNView = static_cast(SfxViewShell::GetNext(*pView, true, checkSfxViewShell)); + 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(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( 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 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(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(); + } + 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( 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(); + } + 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( 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(); + } + 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 + { + SvtCJKOptions aCJKOptions; + if ( !aCJKOptions.IsAsianTypographyEnabled() && ( eHScrollMetric == FieldUnit::CHAR )) + eHScrollMetric = FieldUnit::INCH; + else if ( eHScrollMetric == FieldUnit::CHAR ) + eHScrollMetric = FieldUnit::CM; + if ( !aCJKOptions.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( 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 = rView.GetViewFrame()->GetFrame().GetFrameInterface(); + + uno::Reference xBeamerFrame = xFrame->findFrame("_beamer", FrameSearchFlag::CHILDREN); + if (xBeamerFrame.is()) + { // the beamer has been opened by the SfxViewFrame + Reference xController = xBeamerFrame->getController(); + Reference 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(makeAny(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]; +} + +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. +static boost::property_tree::ptree lcl_AuthorToJson(const OUString& rAuthor, std::size_t nIndex) +{ + boost::property_tree::ptree aRet; + aRet.put("index", nIndex); + aRet.put("name", rAuthor.toUtf8().getStr()); + aRet.put("color", sal_uInt32(lcl_GetAuthorColor(nIndex))); + return aRet; +} + +OUString SwModule::GetRedlineAuthorInfo() +{ + boost::property_tree::ptree aTable; + for (std::size_t nAuthor = 0; nAuthor < m_pAuthorNames.size(); ++nAuthor) + { + boost::property_tree::ptree aAuthor = lcl_AuthorToJson(m_pAuthorNames[nAuthor], nAuthor); + aTable.push_back(std::make_pair("", aAuthor)); + } + + boost::property_tree::ptree aTree; + aTree.add_child("authors", aTable); + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTree); + return OUString::fromUtf8(aStream.str().c_str()); +} + +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(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(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(rAttr.m_nAttr), + RES_CHRATR_UNDERLINE)); + break; + + case SID_ATTR_CHAR_STRIKEOUT: + rSet.Put(SvxCrossedOutItem( static_cast(rAttr.m_nAttr), + RES_CHRATR_CROSSEDOUT)); + break; + + case SID_ATTR_CHAR_CASEMAP: + rSet.Put( SvxCaseMapItem( static_cast(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(); + } + return pPref->GetMetric(); +} + +// Pass-through Update-Status +sal_uInt16 SwModule::GetLinkUpdMode() const +{ + if(!m_pUsrPref) + GetUsrPref(false); + return static_cast(m_pUsrPref->GetUpdateLinkMode()); +} + +SwFieldUpdateFlags SwModule::GetFieldUpdateFlags() const +{ + if(!m_pUsrPref) + GetUsrPref(false); + return m_pUsrPref->GetFieldUpdateFlags(); +} + +void SwModule::ApplyFieldUpdateFlags(SwFieldUpdateFlags eFieldFlags) +{ + if(!m_pUsrPref) + GetUsrPref(false); + m_pUsrPref->SetFieldUpdateFlags(eFieldFlags); +} + +void SwModule::ApplyLinkMode(sal_Int32 nNewLinkMode) +{ + if(!m_pUsrPref) + GetUsrPref(false); + 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 ) + { + for( SwDocShell *pDocSh = static_cast(SfxObjectShell::GetFirst(checkSfxObjectShell)); + pDocSh; + pDocSh = static_cast(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell ) ) ) + { + 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); + 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 000000000..b1e51296f --- /dev/null +++ b/sw/source/uibase/app/swmodule.cxx @@ -0,0 +1,403 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +bool g_bNoInterrupt = false; + +#include + +#include + +#include "swdllimpl.hxx" +#include +#include + +using namespace com::sun::star; +using namespace ::com::sun::star::uno; + +SwModule::SwModule( SfxObjectFactory* pWebFact, + SfxObjectFactory* pFact, + SfxObjectFactory* pGlobalFact ) + : SfxModule("sw", {pWebFact, pFact, pGlobalFact}), + m_pAttrPool(nullptr), + 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); + + StartListening( *SfxGetpApp() ); + + if (!utl::ConfigManager::IsFuzzing()) + { + // init color configuration + // member is created and the color configuration is applied + // at the view options. + GetColorConfig(); + m_xLinguServiceEventListener = new SwLinguServiceEventListener; + } +} + +OUString SwResId(const char* pId) +{ + return Translate::get(pId, SW_MOD()->GetResLocale()); +} + +OUString SwResId(const char* pId, int nCardinality) +{ + return Translate::nget(pId, nCardinality, SW_MOD()->GetResLocale()); +} + +uno::Reference< scanner::XScannerManager2 > const & +SwModule::GetScannerManager() +{ + if (!m_xScannerManager.is()) + { + m_xScannerManager = scanner::ScannerManager::create( comphelper::getProcessComponentContext() ); + } + 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); + + 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 ); + SwNavigationChild::RegisterChildWindowContext( 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); + + 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); + + 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); +} + +void SwModule::RemoveAttrPool() +{ + SetPool(nullptr); + SfxItemPool::Free(m_pAttrPool); +} + +std::unique_ptr SwModule::CreateStyleFamilies() +{ + std::unique_ptr pStyleFamilies(new SfxStyleFamilies); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Para, + SwResId(STR_PARAGRAPHSTYLEFAMILY), + BMP_STYLES_FAMILY_PARA, + RID_PARAGRAPHSTYLEFAMILY, GetResLocale())); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Char, + SwResId(STR_CHARACTERSTYLEFAMILY), + BMP_STYLES_FAMILY_CHAR, + RID_CHARACTERSTYLEFAMILY, GetResLocale())); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Frame, + SwResId(STR_FRAMESTYLEFAMILY), + BMP_STYLES_FAMILY_FRAME, + RID_FRAMESTYLEFAMILY, GetResLocale())); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Page, + SwResId(STR_PAGESTYLEFAMILY), + BMP_STYLES_FAMILY_PAGE, + RID_PAGESTYLEFAMILY, GetResLocale())); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Pseudo, + SwResId(STR_LISTSTYLEFAMILY), + BMP_STYLES_FAMILY_LIST, + RID_LISTSTYLEFAMILY, GetResLocale())); + + pStyleFamilies->emplace_back(SfxStyleFamilyItem(SfxStyleFamily::Table, + SwResId(STR_TABLESTYLEFAMILY), + BMP_STYLES_FAMILY_TABLE, + RID_TABLESTYLEFAMILY, GetResLocale())); + + return pStyleFamilies; +} + +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 000000000..f76b79d0b --- /dev/null +++ b/sw/source/uibase/app/swwait.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 +#include + +#include +#include + +#include + +SwWait::SwWait( + SwDocShell &rDocShell, + const bool bLockUnlockDispatcher ) + : mrDoc ( rDocShell ) + , mbLockUnlockDispatcher( bLockUnlockDispatcher ) + , mpLockedDispatchers() +{ + 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 000000000..1183c4542 --- /dev/null +++ b/sw/source/uibase/chrdlg/ccoll.cxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +//!! 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( const OUString &rContextName ) +{ + sal_Int16 nRes = -1; + for (sal_Int16 i = 0; nRes == -1 && i < COND_COMMAND_COUNT; ++i) + { + if (rContextName.equalsAscii( 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::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(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 000000000..89b72040a --- /dev/null +++ b/sw/source/uibase/config/StoredChapterNumbering.cxx @@ -0,0 +1,476 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +using namespace ::com::sun::star; +using namespace ::xmloff::token; + +namespace sw { + +class StoredChapterNumberingRules + : public ::cppu::WeakImplHelper +{ +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(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>::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 const ret( + SwXNumberingRules::GetPropertiesForNumFormat( + *pNumFormat, *pCharStyleName, &dummy, "")); + return uno::makeAny(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 props; + if (!(rElement >>= props)) + throw lang::IllegalArgumentException("invalid type", + static_cast< ::cppu::OWeakObject*>(this), 1); + + SolarMutexGuard g; + SwNumFormat aNumberFormat; + OUString charStyleName; + SwXNumberingRules::SetPropertiesToNumFormat( + aNumberFormat, + charStyleName, + nullptr, nullptr, nullptr, nullptr, + props); + SwNumRulesWithName *const pRules(GetOrCreateRules()); + pRules->SetNumFormat(nIndex, aNumberFormat, charStyleName); + } +}; + +namespace { + +class StoredChapterNumberingExport + : public SvXMLExport +{ +public: + StoredChapterNumberingExport( + uno::Reference const& xContext, + OUString const& rFileName, + uno::Reference 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 const& xRule) + { + uno::Reference 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 const& rCharStyles, + std::vector> 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 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 + SAL_WARN("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString()); + + 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> m_Contexts; + +public: + StoredChapterNumberingRootContext( + SwChapterNumRules & rNumRules, SvXMLImport & rImport) + : SvXMLImportContext(rImport) + , m_rNumRules(rNumRules) + , m_nCounter(0) + { + } + + virtual void SAL_CALL startFastElement( + sal_Int32 /*nElement*/, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) override {} + + 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 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 const xNamed(xRule, uno::UNO_QUERY); + xNamed->setName((*iter)->GetDisplayName()); + } + } + + virtual SvXMLImportContextRef CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList ) override + { + if (XML_NAMESPACE_TEXT == nPrefix && IsXMLToken(rLocalName, XML_OUTLINE_STYLE)) + { + ++m_nCounter; + if (m_nCounter <= SwChapterNumRules::nMaxRules) + { + SvxXMLListStyleContext *const pContext( + new SvxXMLListStyleContext(GetImport(), + nPrefix, rLocalName, xAttrList, true)); + m_Contexts.emplace_back(pContext); + return pContext; + } + } + return nullptr; + } + + virtual css::uno::Reference SAL_CALL createFastChildContext( + sal_Int32 Element, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override + { + if (Element == XML_ELEMENT(TEXT, XML_OUTLINE_STYLE)) + { + // handled in CreateChildContext + } + else if (Element == XML_ELEMENT(STYLE, XML_STYLE)) + { + return new StoredChapterNumberingDummyStyleContext(GetImport(), xAttrList); + } + + return nullptr; + } +}; + +class StoredChapterNumberingImport + : public SvXMLImport +{ +private: + SwChapterNumRules & m_rNumRules; + +public: + StoredChapterNumberingImport( + uno::Reference 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 const xContext( + ::comphelper::getProcessComponentContext()); + + uno::Reference const xOutStream( + new ::utl::OOutputStreamWrapper(rStream)); + + uno::Reference const xWriter( + xml::sax::Writer::create(xContext)); + + xWriter->setOutputStream(xOutStream); + + rtl::Reference 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 charStyles; + std::vector> 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 const xContext( + ::comphelper::getProcessComponentContext()); + + uno::Reference const xInStream( + new ::utl::OInputStreamWrapper(rStream)); + + rtl::Reference 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 000000000..f57a3b4de --- /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 +#include +#include +#include + +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) + aTbxIdArray[i] = -1; + + Sequence aNames = GetPropertyNames(); + Sequence 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; + 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) + { + aTbxIdArray[nProp] = static_cast(eBarId); + SetModified(); + } +} + +Sequence 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 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 aNames = GetPropertyNames(); + + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + pValues[nProp] <<= 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 000000000..d023bd836 --- /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 +#include + +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 000000000..41ce12460 --- /dev/null +++ b/sw/source/uibase/config/cfgitems.cxx @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + + +SwDocDisplayItem::SwDocDisplayItem() : + SfxPoolItem(FN_PARAM_DOCDISP) +{ + bParagraphEnd = + bTab = + bSpace = + bNonbreakingSpace = + bSoftHyphen = + bCharHiddenText = + bBookmarks = + bManualBreak = true; +}; + +// Item for the Settings dialog, page document view +SwDocDisplayItem::SwDocDisplayItem(const SwViewOption& rVOpt ) : + SfxPoolItem( FN_PARAM_DOCDISP ) +{ + bParagraphEnd = rVOpt.IsParagraph(true); + bTab = rVOpt.IsTab(true); + bSpace = rVOpt.IsBlank(true); + bNonbreakingSpace = rVOpt.IsHardBlank(); + bSoftHyphen = rVOpt.IsSoftHyph(); + bCharHiddenText = rVOpt.IsShowHiddenChar(true); + bBookmarks = rVOpt.IsShowBookmarks(true); + bManualBreak = rVOpt.IsLineBreak(true); +} + +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(rAttr); + + return ( bParagraphEnd == rItem.bParagraphEnd && + bTab == rItem.bTab && + bSpace == rItem.bSpace && + bNonbreakingSpace == rItem.bNonbreakingSpace && + bSoftHyphen == rItem.bSoftHyphen && + bCharHiddenText == rItem.bCharHiddenText && + bBookmarks == rItem.bBookmarks && + bManualBreak == rItem.bManualBreak ); +} + +void SwDocDisplayItem::FillViewOptions( SwViewOption& rVOpt) const +{ + rVOpt.SetParagraph (bParagraphEnd ); + rVOpt.SetTab (bTab ); + rVOpt.SetBlank (bSpace ); + rVOpt.SetHardBlank (bNonbreakingSpace ); + rVOpt.SetSoftHyph (bSoftHyphen ); + rVOpt.SetShowHiddenChar(bCharHiddenText ); + rVOpt.SetShowBookmarks(bBookmarks ); + rVOpt.SetLineBreak (bManualBreak ); +} + +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_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_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(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_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.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(rAttr); + + return SwPrintData::operator==(rItem); +} + +// Item for Settings dialog, ShadowCursorPage +SwShadowCursorItem::SwShadowCursorItem() + : SfxPoolItem( FN_PARAM_SHADOWCURSOR ), + eMode( SwFillMode::Tab ) + ,bOn( false ) +{ +} + +SwShadowCursorItem::SwShadowCursorItem( const SwViewOption& rVOpt ) + : SfxPoolItem( FN_PARAM_SHADOWCURSOR ), + eMode( rVOpt.GetShdwCursorFillMode() ) + ,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(rCmp).IsOn() && + GetMode() == static_cast(rCmp).GetMode(); +} + +void SwShadowCursorItem::FillViewOptions( SwViewOption& rVOpt ) const +{ + rVOpt.SetShadowCursor( bOn ); + rVOpt.SetShdwCursorFillMode( 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( 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 000000000..8df0a7d49 --- /dev/null +++ b/sw/source/uibase/config/dbconfig.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 +#include +#include +#include + +using namespace utl; +using namespace com::sun::star::uno; + +const Sequence& SwDBConfig::GetPropertyNames() +{ + static Sequence 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() +{ + pAdrImpl.reset(); + pBibImpl.reset(); +} + +void SwDBConfig::Load() +{ + const Sequence& rNames = GetPropertyNames(); + if(!pAdrImpl) + { + pAdrImpl.reset(new SwDBData); + pAdrImpl->nCommandType = 0; + pBibImpl.reset(new SwDBData); + pBibImpl->nCommandType = 0; + } + Sequence aValues = GetProperties(rNames); + const Any* pValues = aValues.getConstArray(); + OSL_ENSURE(aValues.getLength() == rNames.getLength(), "GetProperties failed"); + if(aValues.getLength() == rNames.getLength()) + { + for(int nProp = 0; nProp < rNames.getLength(); nProp++) + { + switch(nProp) + { + case 0: pValues[nProp] >>= pAdrImpl->sDataSource; break; + case 1: pValues[nProp] >>= pAdrImpl->sCommand; break; + case 2: pValues[nProp] >>= pAdrImpl->nCommandType; break; + case 3: pValues[nProp] >>= pBibImpl->sDataSource; break; + case 4: pValues[nProp] >>= pBibImpl->sCommand; break; + case 5: pValues[nProp] >>= pBibImpl->nCommandType; break; + } + } + } +} + +const SwDBData& SwDBConfig::GetAddressSource() +{ + if(!pAdrImpl) + Load(); + return *pAdrImpl; +} + +const SwDBData& SwDBConfig::GetBibliographySource() +{ + if(!pBibImpl) + Load(); + return *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 000000000..e58a42bb8 --- /dev/null +++ b/sw/source/uibase/config/fontcfg.cxx @@ -0,0 +1,309 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include + +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 const & SwStdFontConfig::GetPropertyNames() +{ + static Sequence 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++) + { + sDefaultFonts[i] = GetDefaultFor(i, + lcl_LanguageOfType(i, eWestern, eCJK, eCTL)); + nDefaultFontHeight[i] = -1; + } + + Sequence aNames = GetPropertyNames(); + Sequence 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()) + { + if( nProp < DEF_FONT_COUNT) + { + OUString sVal; + pValues[nProp] >>= sVal; + sDefaultFonts[nProp] = sVal; + } + else + { + pValues[nProp] >>= nDefaultFontHeight[nProp - DEF_FONT_COUNT]; + nDefaultFontHeight[nProp - DEF_FONT_COUNT] = convertMm100ToTwip(nDefaultFontHeight[nProp - DEF_FONT_COUNT]); + } + } + } + } +} + +void SwStdFontConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + Sequence 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)) != sDefaultFonts[nProp]) + pValues[nProp] <<= sDefaultFonts[nProp]; + } + else + { + if(nDefaultFontHeight[nProp - DEF_FONT_COUNT] > 0) + pValues[nProp] <<= static_cast(convertTwipToMm100(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 = sDefaultFonts[nFontType] == sDefFont; + break; + case FONT_STANDARD_CJK: + bSame = sDefaultFonts[nFontType] == sDefFontCJK; + break; + case FONT_STANDARD_CTL: + bSame = sDefaultFonts[nFontType] == sDefFontCTL; + break; + case FONT_OUTLINE : + case FONT_OUTLINE_CJK : + case FONT_OUTLINE_CTL : + bSame = sDefaultFonts[nFontType] == + GetDefaultFor(nFontType, eLang); + break; + case FONT_LIST : + case FONT_CAPTION : + case FONT_INDEX : + bSame = sDefaultFonts[nFontType] == sDefFont && + sDefaultFonts[FONT_STANDARD] == sDefFont; + break; + case FONT_LIST_CJK : + case FONT_CAPTION_CJK : + case FONT_INDEX_CJK : + { + bool b1 = sDefaultFonts[FONT_STANDARD_CJK] == sDefFontCJK; + bSame = b1 && sDefaultFonts[nFontType] == sDefFontCJK; + } + break; + case FONT_LIST_CTL : + case FONT_CAPTION_CTL : + case FONT_INDEX_CTL : + { + bool b1 = sDefaultFonts[FONT_STANDARD_CJK] == sDefFontCTL; + bSame = b1 && 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; + } + 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 && nDefaultFontHeight[nFontType] != nHeight) + { + 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 && nDefaultFontHeight[nFontType] > 0 ) + { + SetModified(); + nDefaultFontHeight[nFontType] = -1; + } + else if( !bIsDefaultHeight && nHeight != nDefaultFontHeight[nFontType] ) + { + SetModified(); + 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 = 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 000000000..949aeff1e --- /dev/null +++ b/sw/source/uibase/config/modcfg.cxx @@ -0,0 +1,1334 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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(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(const OUString& rDelim, bool bFromUI) +{ + OUStringBuffer sReturn; + const sal_Int32 nDelimLen = rDelim.getLength(); + if(bFromUI) + { + for (sal_Int32 i = 0; i < nDelimLen; ) + { + const sal_Unicode c = rDelim[i++]; + + if (c == '\\' && i < nDelimLen ) + { + switch (rDelim[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 = rDelim[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 = rDelim[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").append(OUString::number( c, 16 )); + } + else + { + sReturn.append(c); + } + } + } + } + return sReturn.makeStringAndClear(); +} + +const Sequence& SwRevisionConfig::GetPropertyNames() +{ + static Sequence 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_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(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& aNames = GetPropertyNames(); + Sequence 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& aNames = GetPropertyNames(); + Sequence 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(nVal); break; + case 2 : lcl_ConvertCfgToAttr(nVal, m_aDeletedAttr, true); break; + case 3 : m_aDeletedAttr.m_nColor = Color(nVal); break; + case 4 : lcl_ConvertCfgToAttr(nVal, m_aFormatAttr); break; + case 5 : m_aFormatAttr.m_nColor = Color(nVal); break; + case 6 : m_nMarkAlign = sal::static_int_cast< sal_uInt16, sal_Int32>(nVal); break; + case 7 : m_aMarkColor = Color(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& SwInsertConfig::GetPropertyNames() const +{ + static Sequence 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 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(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(rOpt.GetLevel()); break;//Level", + case 7: pValues[nProp] <<= static_cast(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& aNames = GetPropertyNames(); + Sequence 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(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& aNames = GetPropertyNames(); + Sequence 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(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& SwTableConfig::GetPropertyNames() +{ + static Sequence 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& aNames = GetPropertyNames(); + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + switch(nProp) + { + case 0 : pValues[nProp] <<= static_cast(convertTwipToMm100(m_nTableHMove)); break; //"Shift/Row", + case 1 : pValues[nProp] <<= static_cast(convertTwipToMm100(m_nTableVMove)); break; //"Shift/Column", + case 2 : pValues[nProp] <<= static_cast(convertTwipToMm100(m_nTableHInsert)); break; //"Insert/Row", + case 3 : pValues[nProp] <<= static_cast(convertTwipToMm100(m_nTableVInsert)); break; //"Insert/Column", + case 4 : pValues[nProp] <<= static_cast(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& aNames = GetPropertyNames(); + Sequence 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 = static_cast(convertMm100ToTwip(nTemp)); break; //"Shift/Row", + case 1 : pValues[nProp] >>= nTemp; m_nTableVMove = static_cast(convertMm100ToTwip(nTemp)); break; //"Shift/Column", + case 2 : pValues[nProp] >>= nTemp; m_nTableHInsert = static_cast(convertMm100ToTwip(nTemp)); break; //"Insert/Row", + case 3 : pValues[nProp] >>= nTemp; m_nTableVInsert = static_cast(convertMm100ToTwip(nTemp)); break; //"Insert/Column", + case 4 : pValues[nProp] >>= nTemp; m_eTableChgMode = static_cast(nTemp); break; //"Change/Effect", + case 5 : m_bInsTableFormatNum = *o3tl::doAccess(pValues[nProp]); break; //"Input/NumberRecognition", + case 6 : m_bInsTableChangeNumFormat = *o3tl::doAccess(pValues[nProp]); break; //"Input/NumberFormatRecognition", + case 7 : m_bInsTableAlignNum = *o3tl::doAccess(pValues[nProp]); break; //"Input/Alignment" + case 8 : m_bSplitVerticalByDefault = *o3tl::doAccess(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& SwMiscConfig::GetPropertyNames() +{ + static Sequence 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& aNames = GetPropertyNames(); + Sequence 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(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& aNames = GetPropertyNames(); + Sequence 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(pValues[nProp]); break; + case 2 : m_bShowIndexPreview = *o3tl::doAccess(pValues[nProp]); break; + case 3 : m_bGrfToGalleryAsLnk = *o3tl::doAccess(pValues[nProp]); break; + case 4 : m_bNumAlignSize = *o3tl::doAccess(pValues[nProp]); break; + case 5 : m_bSinglePrintJob = *o3tl::doAccess(pValues[nProp]); break; + case 6 : m_nMailingFormats = static_cast(*o3tl::doAccess(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(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(pValues[nProp]); break; + } + } + } +} + +const Sequence& SwCompareConfig::GetPropertyNames() +{ + static Sequence 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& aNames = GetPropertyNames(); + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + pValues[0] <<= static_cast(m_eCmpMode); + pValues[1] <<= m_bUseRsid; + pValues[2] <<= m_bIgnorePieces; + pValues[3] <<= static_cast(m_nPieceLen); + pValues[4] <<= m_bStoreRsid; + + PutProperties(aNames, aValues); +} + +void SwCompareConfig::Load() +{ + const Sequence& aNames = GetPropertyNames(); + Sequence 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(nVal); break; + case 1 : m_bUseRsid = *o3tl::doAccess(pValues[nProp]); break; + case 2 : m_bIgnorePieces = *o3tl::doAccess(pValues[nProp]); break; + case 3 : m_nPieceLen = nVal; break; + case 4 : m_bStoreRsid = *o3tl::doAccess(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 000000000..13831df97 --- /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 +#include +#include +#include +#include + +using namespace utl; +using namespace com::sun::star::uno; + +// Ctor +Sequence 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 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 aNames = GetPropertyNames(); + Sequence 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(pValues[nProp]); break; + case 1: m_bPrintTable = *o3tl::doAccess(pValues[nProp]); break; + case 2: m_bPrintControl = *o3tl::doAccess(pValues[nProp]); break; + case 3: m_bPrintPageBackground= *o3tl::doAccess(pValues[nProp]); break; + case 4: m_bPrintBlackFont = *o3tl::doAccess(pValues[nProp]); break; + case 5: + { + sal_Int32 nTmp = 0; + pValues[nProp] >>= nTmp; + m_nPrintPostIts = static_cast(nTmp); + } + break; + case 6: m_bPrintReverse = *o3tl::doAccess(pValues[nProp]); break; + case 7: m_bPrintProspect = *o3tl::doAccess(pValues[nProp]); break; + case 8: m_bPrintProspectRTL = *o3tl::doAccess(pValues[nProp]); break; + case 9: m_bPrintSingleJobs = *o3tl::doAccess(pValues[nProp]); break; + case 10: pValues[nProp] >>= m_sFaxName; break; + case 11: m_bPaperFromSetup = *o3tl::doAccess(pValues[nProp]); break; + case 12: m_bPrintDraw = *o3tl::doAccess(pValues[nProp]); break; + case 13: m_bPrintLeftPages = *o3tl::doAccess(pValues[nProp]); break; + case 14: m_bPrintRightPages = *o3tl::doAccess(pValues[nProp]); break; + case 15: m_bPrintEmptyPages = *o3tl::doAccess(pValues[nProp]); break; + case 16: m_bPrintTextPlaceholder = *o3tl::doAccess(pValues[nProp]); break; + case 17: m_bPrintHiddenText = *o3tl::doAccess(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 WrtierWeb ... + + m_bPrintDraw = m_bPrintGraphic; +} + +SwPrintOptions::~SwPrintOptions() +{ +} + +void SwPrintOptions::Notify( const css::uno::Sequence< OUString >& ) {} + +void SwPrintOptions::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + + Sequence 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(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 WrtierWeb ... + 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 000000000..0ffee4437 --- /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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; + +#define CHAPTER_FILENAME "chapter.cfg" + +/* + 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->Flush(); + + aMedium.Commit(); + } +} + +SwChapterNumRules::~SwChapterNumRules() +{ +} + +void SwChapterNumRules::Init() +{ + for(auto & rpNumRule : 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(!pNumRules[nIndex]); + pNumRules[nIndex].reset(new SwNumRulesWithName); +} + +void SwChapterNumRules::ApplyNumRules(const SwNumRulesWithName &rCopy, sal_uInt16 nIdx) +{ + assert(nIdx < nMaxRules); + if( !pNumRules[nIdx] ) + pNumRules[nIdx].reset(new SwNumRulesWithName( rCopy )); + else + *pNumRules[nIdx] = rCopy; + Save(); // store it immediately +} + +SwNumRulesWithName::SwNumRulesWithName( const SwNumRule &rCopy, + const OUString &rName ) + : maName(rName) +{ + for( sal_uInt16 n = 0; n < MAXLEVEL; ++n ) + { + const SwNumFormat* pFormat = rCopy.GetNumFormat( n ); + if( pFormat ) + aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat )); + else + 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.aFormats[ n ].get(); + if( pFormat ) + aFormats[ n ].reset(new SwNumFormatGlobal( *pFormat )); + else + aFormats[ n ].reset(); + } + } + return *this; +} + +std::unique_ptr SwNumRulesWithName::MakeNumRule(SwWrtShell& rSh) const +{ + // #i89178# + std::unique_ptr pChg(new SwNumRule(maName, numfunc::GetDefaultPositionAndSpaceMode())); + pChg->SetAutoRule( false ); + for (sal_uInt16 n = 0; n < MAXLEVEL; ++n) + { + SwNumFormatGlobal* pFormat = aFormats[ n ].get(); + if (!pFormat) + continue; + pChg->Set(n, pFormat->MakeNumFormat(rSh)); + } + return pChg; +} + +void SwNumRulesWithName::GetNumFormat( + size_t const nIndex, SwNumFormat const*& rpNumFormat, OUString const*& rpName) const +{ + rpNumFormat = (aFormats[nIndex]) ? &aFormats[nIndex]->aFormat : nullptr; + rpName = (aFormats[nIndex]) ? &aFormats[nIndex]->sCharFormatName : nullptr; +} + +void SwNumRulesWithName::SetNumFormat( + size_t const nIndex, SwNumFormat const& rNumFormat, OUString const& rName) +{ + aFormats[nIndex].reset( new SwNumFormatGlobal(rNumFormat) ); + aFormats[nIndex]->sCharFormatName = rName; + aFormats[nIndex]->nCharPoolId = USHRT_MAX; + aFormats[nIndex]->m_Items.clear(); +} + +SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormat& rFormat ) + : aFormat( rFormat ), nCharPoolId( USHRT_MAX ) +{ + // relative gaps????? + + SwCharFormat* pFormat = rFormat.GetCharFormat(); + if( pFormat ) + { + sCharFormatName = pFormat->GetName(); + nCharPoolId = pFormat->GetPoolFormatId(); + if( pFormat->GetAttrSet().Count() ) + { + SfxItemIter aIter( pFormat->GetAttrSet() ); + const SfxPoolItem *pCurr = aIter.GetCurItem(); + do + { + m_Items.push_back(std::unique_ptr(pCurr->Clone())); + pCurr = aIter.NextItem(); + } while (pCurr); + } + + aFormat.SetCharFormat( nullptr ); + } +} + +SwNumRulesWithName::SwNumFormatGlobal::SwNumFormatGlobal( const SwNumFormatGlobal& rFormat ) + : + aFormat( rFormat.aFormat ), + sCharFormatName( rFormat.sCharFormatName ), + nCharPoolId( rFormat.nCharPoolId ) +{ + for (size_t n = rFormat.m_Items.size(); n; ) + { + m_Items.push_back(std::unique_ptr(rFormat.m_Items[ --n ]->Clone())); + } +} + +SwNumRulesWithName::SwNumFormatGlobal::~SwNumFormatGlobal() +{ +} + +SwNumFormat SwNumRulesWithName::SwNumFormatGlobal::MakeNumFormat(SwWrtShell& rSh) const +{ + SwCharFormat* pFormat = nullptr; + if( !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()==sCharFormatName) + // exists, so leave attributes as they are! + break; + pFormat = nullptr; + } + + if( !pFormat ) + { + if( IsPoolUserFormat( nCharPoolId ) ) + { + pFormat = rSh.MakeCharFormat( sCharFormatName ); + pFormat->SetAuto(false); + } + else + pFormat = rSh.GetCharFormatFromPool( nCharPoolId ); + + if( !pFormat->HasWriterListeners() ) // set attributes + { + for (size_t n = m_Items.size(); n; ) + { + pFormat->SetFormatAttr( *m_Items[ --n ] ); + } + } + } + } + const_cast(aFormat).SetCharFormat(pFormat); + SwNumFormat aNew = aFormat; + if (pFormat) + const_cast(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 000000000..77790b82c --- /dev/null +++ b/sw/source/uibase/config/usrpref.cxx @@ -0,0 +1,599 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace utl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +void SwMasterUsrPref::SetUsrPref(const SwViewOption &rCopy) +{ + *static_cast(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; + 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() +{ +} + +static const auto g_UpdateLinkIndex = 17; + +Sequence 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 + }; +#if defined(__GNUC__) && !defined(__clang__) + // clang 8.0.0 says strcmp isn't constexpr + static_assert(std::strcmp("Update/Link", aPropNames[g_UpdateLinkIndex]) == 0); +#endif + const int nCount = bWeb ? 12 : SAL_N_ELEMENTS(aPropNames); + Sequence 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")), + rParent(rPar), + bWeb(bIsWeb) +{ + Load(); + EnableNotification( GetPropertyNames() ); +} + +SwContentViewConfig::~SwContentViewConfig() +{ +} + +void SwContentViewConfig::Notify( const Sequence< OUString > & /*rPropertyNames*/ ) +{ + Load(); +} + +void SwContentViewConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + bool bVal = false; + switch(nProp) + { + case 0: bVal = rParent.IsGraphic(); break;// "Display/GraphicObject", + case 1: bVal = rParent.IsTable(); break;// "Display/Table", + case 2: bVal = rParent.IsDraw(); break;// "Display/DrawingControl", + case 3: bVal = rParent.IsFieldName(); break;// "Display/FieldCode", + case 4: bVal = rParent.IsPostIts(); break;// "Display/Note", + case 5: bVal = rParent.IsShowContentTips(); break; // "Display/ShowContentTips" + case 6: bVal = rParent.IsViewMetaChars(); break; //"NonprintingCharacter/MetaCharacters" + case 7: bVal = rParent.IsParagraph(true); break;// "NonprintingCharacter/ParagraphEnd", + case 8: bVal = rParent.IsSoftHyph(); break;// "NonprintingCharacter/OptionalHyphen", + case 9: bVal = rParent.IsBlank(true); break;// "NonprintingCharacter/Space", + case 10: bVal = rParent.IsLineBreak(true);break;// "NonprintingCharacter/Break", + case 11: bVal = rParent.IsHardBlank(); break;// "NonprintingCharacter/ProtectedSpace", + case 12: bVal = rParent.IsTab(true); break;// "NonprintingCharacter/Tab", + case 13: bVal = rParent.IsShowHiddenField(); break;// "NonprintingCharacter/Fields: HiddenText", + case 14: bVal = rParent.IsShowHiddenPara(); break;// "NonprintingCharacter/Fields: HiddenParagraph", + case 15: bVal = rParent.IsShowHiddenChar(true); break;// "NonprintingCharacter/HiddenCharacter", + case 16: bVal = rParent.IsShowBookmarks(true); break;// "NonprintingCharacter/Bookmarks", + case 17: pValues[nProp] <<= rParent.GetUpdateLinkMode(); break;// "Update/Link", + case 18: bVal = rParent.IsUpdateFields(); break;// "Update/Field", + case 19: bVal = rParent.IsUpdateCharts(); break;// "Update/Chart" + case 20: bVal = rParent.IsShowInlineTooltips(); break;// "Display/ShowInlineTooltips" + case 21: bVal = rParent.IsUseHeaderFooterMenu(); break;// "Display/UseHeaderFooterMenu" + } + if (nProp != g_UpdateLinkIndex) + pValues[nProp] <<= bVal; + } + PutProperties(aNames, aValues); +} + +void SwContentViewConfig::Load() +{ + Sequence aNames = GetPropertyNames(); + Sequence 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()) + { + bool bSet = nProp != g_UpdateLinkIndex && *o3tl::doAccess(pValues[nProp]); + switch(nProp) + { + case 0: rParent.SetGraphic(bSet); break;// "Display/GraphicObject", + case 1: rParent.SetTable(bSet); break;// "Display/Table", + case 2: rParent.SetDraw(bSet); break;// "Display/DrawingControl", + case 3: rParent.SetFieldName(bSet); break;// "Display/FieldCode", + case 4: rParent.SetPostIts(bSet); break;// "Display/Note", + case 5: rParent.SetShowContentTips(bSet); break;// "Display/ShowContentTips", + case 6: rParent.SetViewMetaChars(bSet); break; //"NonprintingCharacter/MetaCharacters" + case 7: rParent.SetParagraph(bSet); break;// "NonprintingCharacter/ParagraphEnd", + case 8: rParent.SetSoftHyph(bSet); break;// "NonprintingCharacter/OptionalHyphen", + case 9: rParent.SetBlank(bSet); break;// "NonprintingCharacter/Space", + case 10: rParent.SetLineBreak(bSet);break;// "NonprintingCharacter/Break", + case 11: rParent.SetHardBlank(bSet); break;// "NonprintingCharacter/ProtectedSpace", + case 12: rParent.SetTab(bSet); break;// "NonprintingCharacter/Tab", + case 13: rParent.SetShowHiddenField(bSet); break;// "NonprintingCharacter/Fields: HiddenText", + case 14: rParent.SetShowHiddenPara(bSet); break;// "NonprintingCharacter/Fields: HiddenParagraph", + case 15: rParent.SetShowHiddenChar(bSet); break;// "NonprintingCharacter/HiddenCharacter", + case 16: rParent.SetShowBookmarks(bSet); break;// "NonprintingCharacter/Bookmarks", + case 17: + { + sal_Int32 nSet = 0; + pValues[nProp] >>= nSet; + rParent.SetUpdateLinkMode(nSet, true); + } + break;// "Update/Link", + case 18: rParent.SetUpdateFields(bSet); break;// "Update/Field", + case 19: rParent.SetUpdateCharts(bSet); break;// "Update/Chart" + case 20: rParent.SetShowInlineTooltips(bSet); break;// "Display/ShowInlineTooltips" + case 21: rParent.SetUseHeaderFooterMenu(bSet); break;// "Display/UseHeaderFooterMenu" + } + } + } + } +} + +Sequence 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 = bWeb ? 13 : 20; + Sequence 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), + rParent(rPar), + bWeb(bIsWeb) +{ +} + +SwLayoutViewConfig::~SwLayoutViewConfig() +{ +} + +void SwLayoutViewConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + Any &rVal = pValues[nProp]; + switch(nProp) + { + case 0: rVal <<= rParent.IsCrossHair(); break; // "Line/Guide", + case 1: rVal <<= rParent.IsViewHScrollBar(); break; // "Window/HorizontalScroll", + case 2: rVal <<= rParent.IsViewVScrollBar(); break; // "Window/VerticalScroll", + case 3: rVal <<= 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 <<= rParent.IsViewHRuler(true); break; // "Window/HorizontalRuler", + case 5: rVal <<= rParent.IsViewVRuler(true); break; // "Window/VerticalRuler", + case 6: + if(rParent.m_bIsHScrollMetricSet) + rVal <<= static_cast(rParent.m_eHScrollMetric); // "Window/HorizontalRulerUnit" + break; + case 7: + if(rParent.m_bIsVScrollMetricSet) + rVal <<= static_cast(rParent.m_eVScrollMetric); // "Window/VerticalRulerUnit" + break; + case 8: rVal <<= rParent.IsSmoothScroll(); break; // "Window/SmoothScroll", + case 9: rVal <<= static_cast(rParent.GetZoom()); break; // "Zoom/Value", + case 10: rVal <<= static_cast(rParent.GetZoomType()); break; // "Zoom/Type", + case 11: rVal <<= rParent.IsAlignMathObjectsToBaseline(); break; // "Other/IsAlignMathObjectsToBaseline" + case 12: rVal <<= static_cast(rParent.GetMetric()); break; // "Other/MeasureUnit", + case 13: rVal <<= rParent.GetDefTabInMm100(); break;// "Other/TabStop", + case 14: rVal <<= rParent.IsVRulerRight(); break; // "Window/IsVerticalRulerRight", + case 15: rVal <<= static_cast(rParent.GetViewLayoutColumns()); break; // "ViewLayout/Columns", + case 16: rVal <<= rParent.IsViewLayoutBookMode(); break; // "ViewLayout/BookMode", + case 17: rVal <<= rParent.IsSquaredPageMode(); break; // "Other/IsSquaredPageMode", + case 18: rVal <<= rParent.IsApplyCharUnit(); break; // "Other/ApplyCharUnit", + case 19: rVal <<= rParent.IsShowScrollBarTips(); break; // "Window/ShowScrollBarTips", + } + } + PutProperties(aNames, aValues); +} + +void SwLayoutViewConfig::Load() +{ + Sequence aNames = GetPropertyNames(); + Sequence 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 nInt32Val = 0; + bool bSet = false; + pValues[nProp] >>= nInt32Val; + pValues[nProp] >>= bSet; + + switch(nProp) + { + case 0: rParent.SetCrossHair(bSet); break;// "Line/Guide", + case 1: rParent.SetViewHScrollBar(bSet); break;// "Window/HorizontalScroll", + case 2: rParent.SetViewVScrollBar(bSet); break;// "Window/VerticalScroll", + case 3: rParent.SetViewAnyRuler(bSet);break; // "Window/ShowRulers" + case 4: rParent.SetViewHRuler(bSet); break;// "Window/HorizontalRuler", + case 5: rParent.SetViewVRuler(bSet); break;// "Window/VerticalRuler", + case 6: + { + rParent.m_bIsHScrollMetricSet = true; + rParent.m_eHScrollMetric = static_cast(nInt32Val); // "Window/HorizontalRulerUnit" + } + break; + case 7: + { + rParent.m_bIsVScrollMetricSet = true; + rParent.m_eVScrollMetric = static_cast(nInt32Val); // "Window/VerticalRulerUnit" + } + break; + case 8: rParent.SetSmoothScroll(bSet); break;// "Window/SmoothScroll", + case 9: rParent.SetZoom( static_cast< sal_uInt16 >(nInt32Val) ); break;// "Zoom/Value", + case 10: rParent.SetZoomType( static_cast< SvxZoomType >(nInt32Val) ); break;// "Zoom/Type", + case 11: rParent.SetAlignMathObjectsToBaseline(bSet, true); break;// "Other/IsAlignMathObjectsToBaseline" + case 12: rParent.SetMetric(static_cast(nInt32Val), true); break;// "Other/MeasureUnit", + case 13: rParent.SetDefTabInMm100(nInt32Val, true); break;// "Other/TabStop", + case 14: rParent.SetVRulerRight(bSet); break;// "Window/IsVerticalRulerRight", + case 15: rParent.SetViewLayoutColumns( static_cast(nInt32Val) ); break;// "ViewLayout/Columns", + case 16: rParent.SetViewLayoutBookMode(bSet); break;// "ViewLayout/BookMode", + case 17: rParent.SetDefaultPageMode(bSet,true); break;// "Other/IsSquaredPageMode", + case 18: rParent.SetApplyCharUnit(bSet, true); break;// "Other/ApplyUserChar" + case 19: rParent.SetShowScrollBarTips(bSet); break;// "Window/ShowScrollBarTips", + } + } + } + } +} + +void SwLayoutViewConfig::Notify( const css::uno::Sequence< OUString >& ) {} + +Sequence 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 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), + rParent(rPar) +{ +} + +SwGridConfig::~SwGridConfig() +{ +} + +void SwGridConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + switch(nProp) + { + case 0: pValues[nProp] <<= rParent.IsSnap(); break;// "Option/SnapToGrid", + case 1: pValues[nProp] <<= rParent.IsGridVisible(); break;//"Option/VisibleGrid", + case 2: pValues[nProp] <<= rParent.IsSynchronize(); break;// "Option/Synchronize", + case 3: pValues[nProp] <<= static_cast(convertTwipToMm100(rParent.GetSnapSize().Width())); break;// "Resolution/XAxis", + case 4: pValues[nProp] <<= static_cast(convertTwipToMm100(rParent.GetSnapSize().Height())); break;// "Resolution/YAxis", + case 5: pValues[nProp] <<= static_cast(rParent.GetDivisionX()); break;// "Subdivision/XAxis", + case 6: pValues[nProp] <<= static_cast(rParent.GetDivisionY()); break;// "Subdivision/YAxis" + } + } + PutProperties(aNames, aValues); +} + +void SwGridConfig::Load() +{ + Sequence aNames = GetPropertyNames(); + Sequence aValues = GetProperties(aNames); + const Any* pValues = aValues.getConstArray(); + OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed"); + if(aValues.getLength() == aNames.getLength()) + { + Size aSnap(rParent.GetSnapSize()); + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + if(pValues[nProp].hasValue()) + { + bool bSet = nProp < 3 && *o3tl::doAccess(pValues[nProp]); + sal_Int32 nSet = 0; + if(nProp >= 3) + pValues[nProp] >>= nSet; + switch(nProp) + { + case 0: rParent.SetSnap(bSet); break;// "Option/SnapToGrid", + case 1: rParent.SetGridVisible(bSet); break;//"Option/VisibleGrid", + case 2: rParent.SetSynchronize(bSet); break;// "Option/Synchronize", + case 3: aSnap.setWidth( convertMm100ToTwip(nSet) ); break;// "Resolution/XAxis", + case 4: aSnap.setHeight( convertMm100ToTwip(nSet) ); break;// "Resolution/YAxis", + case 5: rParent.SetDivisionX(static_cast(nSet)); break;// "Subdivision/XAxis", + case 6: rParent.SetDivisionY(static_cast(nSet)); break;// "Subdivision/YAxis" + } + } + } + rParent.SetSnapSize(aSnap); + } +} + +void SwGridConfig::Notify( const css::uno::Sequence< OUString >& ) {} + +Sequence SwCursorConfig::GetPropertyNames() +{ + static const char* aPropNames[] = + { + "DirectCursor/UseDirectCursor", // 0 + "DirectCursor/Insert", // 1 + "Option/ProtectedArea", // 2 + }; + const int nCount = SAL_N_ELEMENTS(aPropNames); + Sequence 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), + rParent(rPar) +{ +} + +SwCursorConfig::~SwCursorConfig() +{ +} + +void SwCursorConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + switch(nProp) + { + case 0: pValues[nProp] <<= rParent.IsShadowCursor(); break; // "DirectCursor/UseDirectCursor", + case 1: pValues[nProp] <<= static_cast(rParent.GetShdwCursorFillMode()); break; // "DirectCursor/Insert", + case 2: pValues[nProp] <<= rParent.IsCursorInProtectedArea(); break; // "Option/ProtectedArea" + } + } + PutProperties(aNames, aValues); +} + +void SwCursorConfig::Load() +{ + Sequence aNames = GetPropertyNames(); + Sequence 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()) + { + bool bSet = false; + sal_Int32 nSet = 0; + if(nProp != 1 ) + bSet = *o3tl::doAccess(pValues[nProp]); + else + pValues[nProp] >>= nSet; + switch(nProp) + { + case 0: rParent.SetShadowCursor(bSet); break; // "DirectCursor/UseDirectCursor", + case 1: rParent.SetShdwCursorFillMode(static_cast(nSet)); break; // "DirectCursor/Insert", + case 2: rParent.SetCursorInProtectedArea(bSet); break; // "Option/ProtectedArea" + } + } + } + + } +} + +void SwCursorConfig::Notify( const css::uno::Sequence< OUString >& ) {} + +SwWebColorConfig::SwWebColorConfig(SwMasterUsrPref& rPar) : + ConfigItem("Office.WriterWeb/Background", ConfigItemMode::ReleaseTree), + rParent(rPar), + aPropNames(1) +{ + aPropNames.getArray()[0] = "Color"; +} + +SwWebColorConfig::~SwWebColorConfig() +{ +} + +void SwWebColorConfig::ImplCommit() +{ + Sequence aValues(aPropNames.getLength()); + Any* pValues = aValues.getArray(); + for(int nProp = 0; nProp < aPropNames.getLength(); nProp++) + { + switch(nProp) + { + case 0: pValues[nProp] <<= rParent.GetRetoucheColor(); break;// "Color", + } + } + PutProperties(aPropNames, aValues); +} + +void SwWebColorConfig::Notify( const css::uno::Sequence< OUString >& ) {} + +void SwWebColorConfig::Load() +{ + Sequence aValues = GetProperties(aPropNames); + const Any* pValues = aValues.getConstArray(); + OSL_ENSURE(aValues.getLength() == aPropNames.getLength(), "GetProperties failed"); + if(aValues.getLength() == aPropNames.getLength()) + { + for(int nProp = 0; nProp < aPropNames.getLength(); nProp++) + { + if(pValues[nProp].hasValue()) + { + switch(nProp) + { + case 0: + Color nSet; + pValues[nProp] >>= nSet; 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 000000000..194c89bba --- /dev/null +++ b/sw/source/uibase/config/viewopt.cxx @@ -0,0 +1,582 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +Color SwViewOption::s_aDocBoundColor(COL_LIGHTGRAY); +Color SwViewOption::s_aObjectBoundColor(COL_LIGHTGRAY); +Color SwViewOption::s_aDocColor(COL_LIGHTGRAY); +Color SwViewOption::s_aAppBackgroundColor(COL_LIGHTGRAY); +Color SwViewOption::s_aTableBoundColor(COL_LIGHTGRAY); +Color SwViewOption::s_aIndexShadingsColor(COL_LIGHTGRAY); +Color SwViewOption::s_aLinksColor(COL_BLUE); +Color SwViewOption::s_aVisitedLinksColor(COL_RED); +Color SwViewOption::s_aDirectCursorColor(COL_BLUE); +Color SwViewOption::s_aTextGridColor(COL_LIGHTGRAY); +Color SwViewOption::s_aSpellColor(COL_LIGHTRED); +Color SwViewOption::s_aSmarttagColor(COL_LIGHTMAGENTA); +Color SwViewOption::s_aFontColor(COL_BLACK); +Color SwViewOption::s_aFieldShadingsColor(COL_LIGHTGRAY); +Color SwViewOption::s_aSectionBoundColor(COL_LIGHTGRAY); +Color SwViewOption::s_aPageBreakColor(COL_BLUE); +Color SwViewOption::s_aScriptIndicatorColor(COL_GREEN); +Color SwViewOption::s_aShadowColor(COL_GRAY); +Color SwViewOption::s_aHeaderFooterMarkColor(COL_BLUE); + +ViewOptFlags SwViewOption::s_nAppearanceFlags = ViewOptFlags::DocBoundaries|ViewOptFlags::ObjectBoundaries; +sal_uInt16 SwViewOption::s_nPixelTwips = 0; // one pixel on the screen + +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 +#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 + ; +} + +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 ) +{ + if( pOut && bIsScript ) + { + 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, s_aScriptIndicatorColor ); + pOut->SetLineColor( aOldLineColor ); + } +} + +SwViewOption::SwViewOption() : + 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) +{ + // Initialisation is a little simpler now + // all Bits to 0 + m_nCoreOptions = + ViewOptFlags1::HardBlank | + ViewOptFlags1::SoftHyph | + ViewOptFlags1::Ref | + ViewOptFlags1::Graphic | + ViewOptFlags1::Table | + ViewOptFlags1::Draw | + ViewOptFlags1::Control | + ViewOptFlags1::Pageback | + ViewOptFlags1::Postits; + + 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() && SW_MOD()->GetAccessibilityOptions().IsSelectionInReadonly(); + + m_bIdle = true; + +#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 + if (comphelper::LibreOfficeKit::isActive()) + s_aAppBackgroundColor = COL_TRANSPARENT; +} + +SwViewOption::SwViewOption(const SwViewOption& rVOpt) +{ + m_bReadonly = false; + m_bSelectionInReadonly = false; + // #114856# Form view + 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; + +#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 + 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; + +#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( vcl::Window const *pWin ) +{ + if( !s_nPixelTwips && pWin ) + { + s_nPixelTwips = static_cast(pWin->PixelToLogic( Size(1,1) ).Height()); + } +} + +bool SwViewOption::IsAutoCompleteWords() +{ + const SvxSwAutoFormatFlags& rFlags = SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags(); + return rFlags.bAutoCmpltCollectWords; +} + +void SwViewOption::SetOnlineSpell(bool b) +{ + if (b) + m_nCoreOptions |= ViewOptFlags1::OnlineSpell; + else + m_nCoreOptions &= ~ViewOptFlags1::OnlineSpell; +} + +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( pShell) ) + { + nRet = HTMLMODE_ON | HTMLMODE_SOME_STYLES; + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + switch ( rHtmlOpt.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; +} + +Color& SwViewOption::GetDocColor() +{ + return s_aDocColor; +} + +Color& SwViewOption::GetDocBoundariesColor() +{ + return s_aDocBoundColor; +} + +Color& SwViewOption::GetObjectBoundariesColor() +{ + return s_aObjectBoundColor; +} + +Color& SwViewOption::GetAppBackgroundColor() +{ + return s_aAppBackgroundColor; +} + +Color& SwViewOption::GetTableBoundariesColor() +{ + return s_aTableBoundColor; +} + +Color& SwViewOption::GetIndexShadingsColor() +{ + return s_aIndexShadingsColor; +} + +Color& SwViewOption::GetLinksColor() +{ + return s_aLinksColor; +} + +Color& SwViewOption::GetVisitedLinksColor() +{ + return s_aVisitedLinksColor; +} + +Color& SwViewOption::GetDirectCursorColor() +{ + return s_aDirectCursorColor; +} + +Color& SwViewOption::GetTextGridColor() +{ + return s_aTextGridColor; +} + +Color& SwViewOption::GetSpellColor() +{ + return s_aSpellColor; +} + +Color& SwViewOption::GetSmarttagColor() +{ + return s_aSmarttagColor; +} + +Color& SwViewOption::GetShadowColor() +{ + return s_aShadowColor; +} + +Color& SwViewOption::GetFontColor() +{ + return s_aFontColor; +} + +Color& SwViewOption::GetFieldShadingsColor() +{ + return s_aFieldShadingsColor; +} + +Color& SwViewOption::GetSectionBoundColor() +{ + return s_aSectionBoundColor; +} + +Color& SwViewOption::GetPageBreakColor() +{ + return s_aPageBreakColor; +} + +Color& SwViewOption::GetHeaderFooterMarkColor() +{ + return s_aHeaderFooterMarkColor; +} + +void SwViewOption::ApplyColorConfigValues(const svtools::ColorConfig& rConfig ) +{ + s_aDocColor = rConfig.GetColorValue(svtools::DOCCOLOR).nColor; + + svtools::ColorConfigValue aValue = rConfig.GetColorValue(svtools::DOCBOUNDARIES); + s_aDocBoundColor = aValue.nColor; + s_nAppearanceFlags = ViewOptFlags::NONE; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::DocBoundaries; + + s_aAppBackgroundColor = rConfig.GetColorValue(svtools::APPBACKGROUND).nColor; + + aValue = rConfig.GetColorValue(svtools::OBJECTBOUNDARIES); + s_aObjectBoundColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::ObjectBoundaries; + + aValue = rConfig.GetColorValue(svtools::TABLEBOUNDARIES); + s_aTableBoundColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::TableBoundaries; + + aValue = rConfig.GetColorValue(svtools::WRITERIDXSHADINGS); + s_aIndexShadingsColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::IndexShadings; + + aValue = rConfig.GetColorValue(svtools::LINKS); + s_aLinksColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::Links; + + aValue = rConfig.GetColorValue(svtools::LINKSVISITED); + s_aVisitedLinksColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::VisitedLinks; + + aValue = rConfig.GetColorValue(svtools::SHADOWCOLOR); + s_aShadowColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::Shadow; + + s_aDirectCursorColor = rConfig.GetColorValue(svtools::WRITERDIRECTCURSOR).nColor; + + s_aTextGridColor = rConfig.GetColorValue(svtools::WRITERTEXTGRID).nColor; + + s_aSpellColor = rConfig.GetColorValue(svtools::SPELL).nColor; + + s_aSmarttagColor = rConfig.GetColorValue(svtools::SMARTTAGS).nColor; + + s_aFontColor = rConfig.GetColorValue(svtools::FONTCOLOR).nColor; + + aValue = rConfig.GetColorValue(svtools::WRITERFIELDSHADINGS); + s_aFieldShadingsColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::FieldShadings; + + aValue = rConfig.GetColorValue(svtools::WRITERSECTIONBOUNDARIES); + s_aSectionBoundColor = aValue.nColor; + if(aValue.bIsVisible) + s_nAppearanceFlags |= ViewOptFlags::SectionBoundaries; + + aValue = rConfig.GetColorValue(svtools::WRITERPAGEBREAKS); + s_aPageBreakColor = aValue.nColor; + + aValue = rConfig.GetColorValue(svtools::WRITERHEADERFOOTERMARK); + s_aHeaderFooterMarkColor = aValue.nColor; + + s_aScriptIndicatorColor = rConfig.GetColorValue(svtools::WRITERSCRIPTINDICATOR).nColor; +} + +void SwViewOption::SetAppearanceFlag(ViewOptFlags nFlag, bool bSet, bool bSaveInConfig ) +{ + if(bSet) + s_nAppearanceFlags |= nFlag; + else + s_nAppearanceFlags &= ~nFlag; + if(bSaveInConfig) + { + //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) +{ + return bool(s_nAppearanceFlags & nFlag); +} + +namespace{ +rtl::Reference const & getWCOptionListener() +{ + static rtl::Reference xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Writer/Cursor/Option")); + return xListener; +} +} + +bool SwViewOption::IsIgnoreProtectedArea() +{ + static comphelper::ConfigurationListenerProperty gIgnoreProtectedArea(getWCOptionListener(), "IgnoreProtectedArea"); + return gIgnoreProtectedArea.get(); +} + +/* 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 000000000..7af8c114f --- /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 inidividual 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 000000000..309d74ae8 --- /dev/null +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -0,0 +1,3366 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; +using namespace sw; + +#define DB_SEP_SPACE 0 +#define DB_SEP_TAB 1 +#define DB_SEP_RETURN 2 +#define DB_SEP_NEWLINE 3 + +namespace { + +void lcl_emitEvent(SfxEventHintId nEventId, sal_Int32 nStrId, SfxObjectShell* pDocShell) +{ + SfxGetpApp()->NotifyEvent(SfxEventHint(nEventId, + SwDocShell::GetEventName(nStrId), + pDocShell)); +} + +} + +std::vector> SwDBManager::m_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, SwDoc** const pDoc ); + +static bool lcl_getCountFromResultSet( sal_Int32& rCount, const SwDSParam* pParam ) +{ + rCount = pParam->aSelection.getLength(); + if ( rCount > 0 ) + return true; + + uno::Reference 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 +{ + uno::Reference 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 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; + + OUString aOwnURL = pDocShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::WithCharset); + OUString sTmpName = "vnd.sun.star.pkg://" + + INetURLObject::encode(aOwnURL, INetURLObject::PART_AUTHORITY, INetURLObject::EncodeMechanism::All); + sTmpName += "/" + 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 pMergeData; + VclPtr pMergeDialog; + rtl::Reference m_xDisposeListener; + rtl::Reference m_xDataSourceRemovedListener; + osl::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 const & xSource) +{ + uno::Reference xContext = ::comphelper::getProcessComponentContext(); + rParam.xFormatter = util::NumberFormatter::create(xContext); + uno::Reference xSourceProps( + (xSource.is() + ? xSource + : SwDBManager::getDataSourceAsParent( + rParam.xConnection, rParam.sDataSource)), + uno::UNO_QUERY); + if(xSourceProps.is()) + { + uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier"); + if(aFormats.hasValue()) + { + uno::Reference 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, 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 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 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; + SwDoc *pWorkDoc = nullptr; + 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 xResSet; + uno::Sequence 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(*m_pImpl->pMergeData)); + try + { + uno::Reference xComponent(m_DataSourceParams.back()->xConnection, uno::UNO_QUERY); + if(xComponent.is()) + xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); + } + 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 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 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) + { + pSh->StartAllAction(); + pSh->StartUndo(); + bool bGroupUndo(pSh->DoesGroupUndo()); + pSh->DoGroupUndo(false); + + if( pSh->HasSelection() ) + pSh->DelRight(); + + std::unique_ptr pWait; + + { + sal_uLong i = 0; + do { + + ImportDBEntry(pSh); + if( 10 == ++i ) + pWait.reset(new SwWait( *pSh->GetView().GetDocShell(), true)); + + } while(ToNextMergeRecord()); + } + + pSh->DoGroupUndo(bGroupUndo); + pSh->EndUndo(); + pSh->EndAllAction(); + } +} + +static OUString lcl_FindColumn(const OUString& sFormatStr,sal_uInt16 &nUsedPos, sal_uInt8 &nSeparator) +{ + OUStringBuffer sReturn; + sal_uInt16 nLen = sFormatStr.getLength(); + nSeparator = 0xff; + while(nUsedPos < nLen && nSeparator == 0xff) + { + sal_Unicode cCurrent = sFormatStr[nUsedPos]; + switch(cCurrent) + { + case ',': + nSeparator = DB_SEP_SPACE; + break; + case ';': + nSeparator = DB_SEP_RETURN; + break; + case ':': + nSeparator = DB_SEP_TAB; + break; + case '#': + nSeparator = DB_SEP_NEWLINE; + break; + default: + sReturn.append(cCurrent); + } + nUsedPos++; + + } + return sReturn.makeStringAndClear(); +} + +void SwDBManager::ImportDBEntry(SwWrtShell* pSh) +{ + if(m_pImpl->pMergeData && !m_pImpl->pMergeData->bEndOfDB) + { + uno::Reference< sdbcx::XColumnsSupplier > xColsSupp( m_pImpl->pMergeData->xResultSet, uno::UNO_QUERY ); + uno::Reference xCols = xColsSupp->getColumns(); + OUString sFormatStr; + sal_uInt16 nFormatLen = sFormatStr.getLength(); + if( nFormatLen ) + { + const char cSpace = ' '; + const char cTab = '\t'; + sal_uInt16 nUsedPos = 0; + sal_uInt8 nSeparator; + OUString sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator); + while( !sColumn.isEmpty() ) + { + if(!xCols->hasByName(sColumn)) + return; + uno::Any aCol = xCols->getByName(sColumn); + uno::Reference< beans::XPropertySet > xColumnProp; + aCol >>= xColumnProp; + if(xColumnProp.is()) + { + SwDBFormatData aDBFormat; + OUString sInsert = GetDBField( xColumnProp, aDBFormat); + if( DB_SEP_SPACE == nSeparator ) + sInsert += OUStringChar(cSpace); + else if( DB_SEP_TAB == nSeparator) + sInsert += OUStringChar(cTab); + pSh->Insert(sInsert); + if( DB_SEP_RETURN == nSeparator) + pSh->SplitNode(); + else if(DB_SEP_NEWLINE == nSeparator) + pSh->InsertLineBreak(); + } + else + { + // column not found -> show error + OUString sInsert = "?" + sColumn + "?"; + pSh->Insert(sInsert); + } + sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator); + } + pSh->SplitNode(); + } + else + { + OUStringBuffer sStr; + uno::Sequence aColNames = xCols->getElementNames(); + const OUString* pColNames = aColNames.getConstArray(); + long nLength = aColNames.getLength(); + for(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 xTSupplier(xConnection, uno::UNO_QUERY); + if(xTSupplier.is()) + { + uno::Reference xTables = xTSupplier->getTables(); + const uno::Sequence aTables = xTables->getElementNames(); + for (const OUString& rTable : aTables) + rBox.append("0", rTable); + } + uno::Reference xQSupplier(xConnection, uno::UNO_QUERY); + if(xQSupplier.is()) + { + uno::Reference xQueries = xQSupplier->getQueries(); + const uno::Sequence 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 xCols = xColsSupp->getColumns(); + const uno::Sequence 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) +{ +} + +SwDBManager::~SwDBManager() COVERITY_NOEXCEPT_FALSE +{ + RevokeLastRegistrations(); + + // copy required, m_DataSourceParams can be modified while disposing components + std::vector> aCopiedConnections; + for (const auto & pParam : m_DataSourceParams) + { + if(pParam->xConnection.is()) + { + aCopiedConnections.push_back(pParam->xConnection); + } + } + for (const auto & xConnection : aCopiedConnections) + { + try + { + uno::Reference 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 + } + } +} + +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::TempFile 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; + + const OUString sExt( ".odt" ); + OUString basename = OUString::createFromAscii( name ); + if (no > 0) + basename += OUString::number(no) + "-"; + // aTempFile is not deleted, but that seems to be intentional + utl::TempFile aTempFile( basename, true, &sExt, &sTempDirURL ); + INetURLObject aTempFileURL( aTempFile.GetURL() ); + auto pDstMed = std::make_unique( + 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->GetError()); + 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& 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( pDstMed->GetItemSet() ) + { + if( pStoreToFilterOptions ) + pDstMed->GetItemSet()->Put( SfxStringItem(SID_FILE_FILTEROPTIONS, + *pStoreToFilterOptions)); + if( pSaveToFilterData->hasElements() ) + pDstMed->GetItemSet()->Put( SfxUnoAnyItem(SID_FILTER_DATA, + uno::makeAny(*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->GetError()); + if( bAnyError ) + { + // error message ?? + ErrorHandler::HandleError( xObjectShell->GetError() ); + } + 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 + + const sal_Int32 nOffset = 1; + rOutPrintOptions.realloc( nOffset ); + rOutPrintOptions[ 0 ].Name = "Wait"; + rOutPrintOptions[ 0 ].Value <<= true; + + // copy print options + sal_Int32 nIndex = nOffset; + 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 ); + rOutPrintOptions[ nIndex ].Name = rOption.Name; + rOutPrintOptions[ nIndex++ ].Value = rOption.Value ; + } + } +} + +static void lcl_PrepareSaveFilterDataOptions( + const uno::Sequence< beans::PropertyValue >& rInSaveFilterDataptions, + uno::Sequence< beans::PropertyValue >& rOutSaveFilterDataOptions, + const OUString& sPassword) +{ + const sal_Int32 nOffset = 2; + rOutSaveFilterDataOptions.realloc( nOffset ); + rOutSaveFilterDataOptions[ 0 ].Name = "EncryptFile"; + rOutSaveFilterDataOptions[ 0 ].Value <<= true; + rOutSaveFilterDataOptions[ 1 ].Name = "DocumentOpenPassword"; + rOutSaveFilterDataOptions[ 1 ].Value <<= sPassword; + + // copy other options + sal_Int32 nIndex = nOffset; + for( const beans::PropertyValue& rOption : rInSaveFilterDataptions) + { + rOutSaveFilterDataOptions.realloc( nIndex + 1 ); + rOutSaveFilterDataOptions[ nIndex ].Name = rOption.Name; + rOutSaveFilterDataOptions[ 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, 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() ); + 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(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 SwMailMessage* lcl_CreateMailFromDoc( + const SwMergeDescriptor &rMergeDescriptor, + const OUString &sFileURL, const OUString &sMailRecipient, + const OUString &sMailBodyMimeType, rtl_TextEncoding sMailEncoding, + const OUString &sAttachmentMimeType ) +{ + 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 ); + OString sLine; + while ( pInStream->ReadLine( sLine ) ) + { + sBody.append(OStringToOUString( sLine, sMailEncoding )); + sBody.append("\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 + { + osl::MutexGuard 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 xMailDispatcher, + uno::Reference< mail::XMailMessage>, const OUString& ) override + { + osl::MutexGuard 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 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=" + OUString::createFromAscii( + rtl_getBestMimeCharsetFromTextEncoding( sMailEncoding )); + SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); + sMailEncoding = rHtmlOptions.GetTextEncoding(); + } + else + sMailBodyMimeType = "text/plain; charset=UTF-8; format=flowed"; + } + } + + SwDocShell *pSourceDocSh = pSourceShell->GetView().GetDocShell(); + + // setup the output format + std::shared_ptr 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 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"; + + 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; + SwDoc* pTargetDoc = nullptr; + SfxObjectShellRef xTargetDocShell; + + std::unique_ptr< utl::TempFile > aTempFile; + sal_uInt16 nStartingPageNo = 0; + + vcl::Window *pSourceWindow = nullptr; + std::shared_ptr xProgressDlg; + + try + { + if( !bIsMergeSilent ) + { + // construct the process dialog + pSourceWindow = &pSourceShell->GetView().GetEditWin(); + if (!bMT_PRINTER) + xProgressDlg = std::make_shared(pSourceWindow->GetFrameWeld()); + else + { + xProgressDlg = std::make_shared(pSourceWindow->GetFrameWeld()); + static_cast(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(); + 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(xProgressDlg.get())->SetTotalCount(nMaxDocs); + } + + long 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; + SwDoc* pWorkDoc = nullptr; + 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::TempFile(sLeading, sColumnData.isEmpty(), &sExt, &sPrefix, true) ); + if( !aTempFile->IsValid() ) + { + ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); + m_aMergeStatus = MergeStatus::Error; + } + } + + OUString sPasswordColumnData; + uno::Sequence< beans::PropertyValue > aSaveToFilterDataOptions( rMergeDescriptor.aSaveToFilterData ); + + if( bMT_EMAIL || bPasswordColumnName ) + { + 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(xProgressDlg.get())->SetCurrentPosition(nDocNo); + else { + PrintMonitor *pPrintMonDlg = static_cast(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 ) + { + 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) + { + uno::Reference< uno::XInterface > xRef( + static_cast(const_cast(pEvtSrc)) ); + text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() ); + pEvtSrc->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( + appendedDocStart, "", IDocumentMarkAccess::MarkType::UNO_BOOKMARK, + ::sw::mark::InsertMode::New); + aMergeInfo.nDBRow = nStartRow; + rMergeDescriptor.pMailMergeConfigItem->AddMergedDocument( aMergeInfo ); + } + } + else + { + assert( bNeedsTempFiles ); + assert( pWorkShell->IsExpFieldsLocked() ); + + // 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() ) + { + osl::MutexGuard aGuard( m_pImpl->m_aAllEmailSendMutex ); + m_pImpl->m_xLastMessage.set( xMessage ); + xMailDispatcher->enqueueMailMessage( xMessage ); + if( !xMailDispatcher->isStarted() ) + xMailDispatcher->start(); + } + } + } + } + if( bCreateSingleFile || bIsPDFexport ) + { + pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); + 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 ) + { + pWorkDoc->SetDBManager( pWorkDocOrigDBManager ); + 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; + aEmailDispatcherPollTimer.SetDebugName( + "sw::SwDBManager aEmailDispatcherPollTimer" ); + aEmailDispatcherPollTimer.SetTimeout( 500 ); + aEmailDispatcherPollTimer.Start(); + while( IsMergeOk() && m_pImpl->m_xLastMessage.is() ) + 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_uLong SwDBManager::GetColumnFormat( const OUString& rDBName, + const OUString& rTableName, + const OUString& rColNm, + SvNumberFormatter* pNFormatr, + LanguageType nLanguage ) +{ + sal_uLong 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 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_uLong 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_uLong nRet = 0; + + if(!xSource.is()) + { + uno::Reference xChild(xConnection, uno::UNO_QUERY); + if ( xChild.is() ) + xSource.set(xChild->getParent(), uno::UNO_QUERY); + } + if(xSource.is() && xConnection.is() && xColumn.is() && pNFormatr) + { + SvNumberFormatsSupplierObj* pNumFormat = new SvNumberFormatsSupplierObj( pNFormatr ); + uno::Reference< util::XNumberFormatsSupplier > xDocNumFormatsSupplier = pNumFormat; + uno::Reference< util::XNumberFormats > xDocNumberFormats = xDocNumFormatsSupplier->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 xSourceProps(xSource, uno::UNO_QUERY); + uno::Reference< util::XNumberFormats > xNumberFormats; + if(xSourceProps.is()) + { + uno::Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier"); + if(aFormats.hasValue()) + { + uno::Reference 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 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 xCols = xColsSupp->getColumns(); + if(xCols->hasByName(rColNm)) + { + uno::Any aCol = xCols->getByName(rColNm); + uno::Reference 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& rxSource, const SwView *pView) +{ + uno::Reference< sdbc::XConnection> xConnection; + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + try + { + uno::Reference 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 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 xTSupplier(xConnection, uno::UNO_QUERY); + if(xTSupplier.is()) + { + uno::Reference 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 xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), uno::UNO_QUERY); + + OUString sDataSource; + uno::Reference xSource = SwDBManager::getDataSourceAsParent(xConnection, sDataSource); + uno::Reference xSourceProperties(xSource, uno::UNO_QUERY); + if(xSourceProperties.is()) + { + xSourceProperties->getPropertyValue("Name") >>= sDataSource; + } + + uno::Reference xRowProperties(xRowSet, uno::UNO_QUERY); + xRowProperties->setPropertyValue("DataSourceName", uno::makeAny(sDataSource)); + xRowProperties->setPropertyValue("Command", uno::makeAny(rTableOrQuery)); + xRowProperties->setPropertyValue("CommandType", uno::makeAny(nCommandType)); + xRowProperties->setPropertyValue("FetchSize", uno::makeAny(sal_Int32(10))); + xRowProperties->setPropertyValue("ActiveConnection", uno::makeAny(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 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(pFound->aSelection.begin(), pFound->aSelection.end(), + [nAbsRecordId](const uno::Any& rSelection) { + sal_Int32 nSelection = 0; + rSelection >>= nSelection; + return nSelection == static_cast(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(nAbsRecordId) ) + bMove = lcl_MoveAbsolute(pFound, nAbsRecordId); + if(bMove) + bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber); + if ( nOldRow != static_cast(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 xCols = xColsSupp->getColumns(); + const uno::Sequence 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 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 xComponent(pFound->xConnection, uno::UNO_QUERY); + if(xComponent.is()) + xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); + } + 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(pFound)); + try + { + uno::Reference xComponent(pFound->xConnection, uno::UNO_QUERY); + if(xComponent.is()) + xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); + } + 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(pFound)); + try + { + uno::Reference xComponent(pFound->xConnection, uno::UNO_QUERY); + if(xComponent.is()) + xComponent->addEventListener(m_pImpl->m_xDisposeListener.get()); + } + catch(const uno::Exception&) + { + } + } + return pFound; +} + +const SwDBData& SwDBManager::GetAddressDBName() +{ + return SW_MOD()->GetDBConfig()->GetAddressSource(); +} + +uno::Sequence SwDBManager::GetExistingDatabaseNames() +{ + uno::Reference xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference 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::Sequence aFilters(1); + + 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 + aFilters[0] = rURL.getBase(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); + aTableFilterAny <<= aFilters; + break; + case DBConnURIType::MSJET: + case DBConnURIType::MSACE: + aSuppressVersionsAny <<= true; + break; + } + + try + { + uno::Reference xContext(::comphelper::getProcessComponentContext()); + uno::Reference 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, ""); + + //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 xNewInstance; + if (!bStore) + { + //odb-file + uno::Any aDataSource = xDBContext->getByName(rURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + aDataSource >>= xNewInstance; + } + else + { + xNewInstance = xDBContext->createInstance(); + uno::Reference 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::makeAny(sExt)); + } + + uno::Reference xDS(xNewInstance, uno::UNO_QUERY_THROW); + uno::Reference 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 const sOutputExt = ".odb"; + OUString sHomePath(SvtPathOptions().GetWorkPath()); + utl::TempFile aTempFile(sNewName, true, &sOutputExt, pDestDir ? pDestDir : &sHomePath); + const OUString& sTmpName = aTempFile.GetURL(); + xStore->storeAsURL(sTmpName, uno::Sequence()); + } + else + { + // Embed. + OUString aStreamRelPath = "EmbeddedDatabase"; + uno::Reference 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 xFactory(pDocShell->GetModel(), uno::UNO_QUERY); + uno::Reference xPropertySet(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY); + xPropertySet->setPropertyValue("EmbeddedDatabaseName", uno::makeAny(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; +} + +// Construct vnd.sun.star.pkg:// URL +OUString ConstructVndSunStarPkgUrl(const OUString& rMainURL, const OUString& 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); +} +} + +OUString SwDBManager::LoadAndRegisterDataSource(weld::Window* pParent, SwDocShell* pDocShell) +{ + sfx2::FileDialogHelper aDlgHelper(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, FileDialogFlags::NONE, pParent); + uno::Reference < ui::dialogs::XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + OUString sHomePath(SvtPathOptions().GetWorkPath()); + aDlgHelper.SetDisplayDirectory( sHomePath ); + + OUString sFilterAll(SwResId(STR_FILTER_ALL)); + OUString sFilterAllData(SwResId(STR_FILTER_ALL_DATA)); + OUString sFilterSXB(SwResId(STR_FILTER_SXB)); + OUString sFilterSXC(SwResId(STR_FILTER_SXC)); + OUString sFilterSXW(SwResId(STR_FILTER_SXW)); + OUString sFilterDBF(SwResId(STR_FILTER_DBF)); + OUString sFilterXLS(SwResId(STR_FILTER_XLS)); + OUString sFilterDOC(SwResId(STR_FILTER_DOC)); + OUString sFilterTXT(SwResId(STR_FILTER_TXT)); + OUString sFilterCSV(SwResId(STR_FILTER_CSV)); +#ifdef _WIN32 + OUString sFilterMDB(SwResId(STR_FILTER_MDB)); + OUString sFilterACCDB(SwResId(STR_FILTER_ACCDB)); +#endif + xFP->appendFilter( sFilterAll, "*" ); + xFP->appendFilter( sFilterAllData, "*.ods;*.sxc;*.odt;*.sxw;*.dbf;*.xls;*.xlsx;*.doc;*.docx;*.txt;*.csv"); + + xFP->appendFilter( sFilterSXB, "*.odb" ); + xFP->appendFilter( sFilterSXC, "*.ods;*.sxc" ); + xFP->appendFilter( sFilterSXW, "*.odt;*.sxw" ); + xFP->appendFilter( sFilterDBF, "*.dbf" ); + xFP->appendFilter( sFilterXLS, "*.xls;*.xlsx" ); + xFP->appendFilter( sFilterDOC, "*.doc;*.docx" ); + xFP->appendFilter( sFilterTXT, "*.txt" ); + xFP->appendFilter( sFilterCSV, "*.csv" ); +#ifdef _WIN32 + xFP->appendFilter(sFilterMDB, "*.mdb;*.mde"); + xFP->appendFilter(sFilterACCDB, "*.accdb;*.accde"); +#endif + + xFP->setCurrentFilter( sFilterAll ) ; + OUString sFind; + if( ERRCODE_NONE == aDlgHelper.Execute() ) + { + uno::Reference< beans::XPropertySet > aSettings; + const INetURLObject aURL( xFP->getSelectedFiles().getConstArray()[0] ); + const DBConnURIType type = GetDBunoType( aURL ); + + if( DBConnURIType::FLAT == type ) + { + uno::Reference 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 ); + + m_aUncommittedRegistrations.push_back(std::pair(pDocShell, sFind)); + } + return sFind; +} + +void SwDBManager::StoreEmbeddedDataSource(const uno::Reference& xStorable, + const uno::Reference& 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 aSequence = comphelper::InitPropertySequence( + { + {"TargetStorage", uno::makeAny(xStorage)}, + {"StreamRelPath", uno::makeAny(rStreamRelPath)}, + {"BaseURI", uno::makeAny(rOwnURL)} + }); + if (bCopyTo) + xStorable->storeToURL(sTmpName, aSequence); + else + xStorable->storeAsURL(sTmpName, aSequence); +} + +OUString SwDBManager::LoadAndRegisterDataSource(const OUString &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& rDatabaseContext, const OUString& rName) + { + uno::Reference xDS(rDatabaseContext->getByName(rName), uno::UNO_QUERY); + if (!xDS) + return; + uno::Reference xStorageDoc(xDS->getDatabaseDocument(), uno::UNO_QUERY); + if (!xStorageDoc) + return; + xStorageDoc->switchToStorage(comphelper::OStorageHelper::GetTemporaryStorage()); + } +} + +void SwDBManager::RevokeDataSource(const OUString& rName) +{ + uno::Reference 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 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 xDataSource(xDatabaseContext->getByName(aURL), uno::UNO_QUERY); + xDatabaseContext->registerObject( sDataSource, xDataSource ); + + // temp file - don't remember connection + if (rData.sDataSource.isEmpty()) + m_aUncommittedRegistrations.push_back(std::pair(nullptr, sDataSource)); +} + +void SwDBManager::ExecuteFormLetter( SwWrtShell& rSh, + const uno::Sequence& rProperties) +{ + //prevent second call + if(m_pImpl->pMergeDialog) + return ; + OUString sDataSource, sDataTableOrQuery; + uno::Sequence 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()->GetWindow().GetFrameWeld(), rSh, + sDataSource, + sDataTableOrQuery, + nCmdType, + xConnection); + if(m_pImpl->pMergeDialog->Execute() == RET_OK) + { + aDescriptor[svx::DataAccessDescriptorProperty::Selection] <<= m_pImpl->pMergeDialog->GetSelection(); + + uno::Reference 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 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 xResSet; + uno::Sequence 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 xSource; + uno::Reference 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 pDlg(pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(), + xSource, + xColSupp, + aDBData )); + if( RET_OK == pDlg->Execute() ) + { + 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 SwDBManager::getDataSourceAsParent(const uno::Reference< sdbc::XConnection>& _xConnection,const OUString& _sDataSourceName) +{ + uno::Reference xSource; + try + { + uno::Reference 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 SwDBManager::createCursor(const OUString& _sDataSourceName, + const OUString& _sCommand, + sal_Int32 _nCommandType, + const uno::Reference& _xConnection, + const SwView* pView) +{ + uno::Reference xResultSet; + try + { + uno::Reference< lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); + if( xMgr.is() ) + { + uno::Reference xInstance = xMgr->createInstance("com.sun.star.sdb.RowSet"); + uno::Reference xRowSetPropSet(xInstance, uno::UNO_QUERY); + if(xRowSetPropSet.is()) + { + xRowSetPropSet->setPropertyValue("DataSourceName", uno::makeAny(_sDataSourceName)); + xRowSetPropSet->setPropertyValue("ActiveConnection", uno::makeAny(_xConnection)); + xRowSetPropSet->setPropertyValue("Command", uno::makeAny(_sCommand)); + xRowSetPropSet->setPropertyValue("CommandType", uno::makeAny(_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 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 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 SwDBManager::PerformMailMerge(SwView const * pView) +{ + std::shared_ptr 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 (!m_aUncommittedRegistrations.empty()) + { + SwView* pView = ( m_pDoc && m_pDoc->GetDocShell() ) ? m_pDoc->GetDocShell()->GetView() : nullptr; + if (pView) + { + const std::shared_ptr& xConfigItem = pView->GetMailMergeConfigItem(); + if (xConfigItem) + { + xConfigItem->DisposeResultSet(); + xConfigItem->DocumentReloaded(); + } + } + + for (auto it = m_aUncommittedRegistrations.begin(); it != m_aUncommittedRegistrations.end();) + { + if ((m_pDoc && it->first == m_pDoc->GetDocShell()) || it->first == nullptr) + { + RevokeDataSource(it->second); + it = m_aUncommittedRegistrations.erase(it); + } + else + ++it; + } + } +} + +void SwDBManager::CommitLastRegistrations() +{ + for (auto aIt = m_aUncommittedRegistrations.begin(); aIt != m_aUncommittedRegistrations.end();) + { + if (aIt->first == m_pDoc->GetDocShell() || aIt->first == nullptr) + { + m_aNotUsedConnections.push_back(aIt->second); + aIt = m_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 000000000..cf31941c3 --- /dev/null +++ b/sw/source/uibase/dbui/dbtree.cxx @@ -0,0 +1,435 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +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& GetContext() const {return m_xDatabaseContext;} + Reference 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 SwDBTreeList_Impl::GetConnection(const OUString& rSourceName) +{ + Reference xRet; + if (m_xDatabaseContext.is() && m_pWrtShell) + { + xRet = m_pWrtShell->GetDBManager()->RegisterConnection(rSourceName); + } + return xRet; +} + +SwDBTreeList::SwDBTreeList(std::unique_ptr xTreeView) + : bInitialized(false) + , bShowColumns(false) + , pImpl(new SwDBTreeList_Impl) + , m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->connect_expanding(LINK(this, SwDBTreeList, RequestingChildrenHdl)); +} + +SwDBTreeList::~SwDBTreeList() +{ +} + +void SwDBTreeList::InitTreeList() +{ + if (!pImpl->HasContext() && pImpl->GetWrtShell()) + return; + + Sequence< OUString > aDBNames = pImpl->GetContext()->getElementNames(); + auto const sort = comphelper::string::NaturalStringSorter( + comphelper::getProcessComponentContext(), + Application::GetSettings().GetUILanguageTag().getLocale()); + std::sort( + aDBNames.begin(), aDBNames.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)) + { + Reference xConnection = pImpl->GetConnection(rDBName); + if (xConnection.is()) + { + m_xTreeView->insert(nullptr, -1, &rDBName, nullptr, nullptr, nullptr, &aImg, true, nullptr); + } + } + Select(OUString(), OUString(), OUString()); + + bInitialized = true; +} + +void SwDBTreeList::AddDataSource(const OUString& rSource) +{ + OUString aImg(RID_BMP_DB); + std::unique_ptr xIter(m_xTreeView->make_iterator()); + m_xTreeView->insert(nullptr, -1, &rSource, nullptr, nullptr, nullptr, &aImg, true, xIter.get()); + m_xTreeView->select(*xIter); +} + +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 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(!pImpl->GetContext()->hasByName(sSourceName)) + return true; + Reference xConnection = pImpl->GetConnection(sSourceName); + bool bTable = m_xTreeView->get_id(rParent).isEmpty(); + Reference xColsSupplier; + if(bTable) + { + Reference xTSupplier(xConnection, UNO_QUERY); + if(xTSupplier.is()) + { + Reference xTables = xTSupplier->getTables(); + OSL_ENSURE(xTables->hasByName(sTableName), "table not available anymore?"); + try + { + Any aTable = xTables->getByName(sTableName); + Reference xPropSet; + aTable >>= xPropSet; + xColsSupplier.set(xPropSet, UNO_QUERY); + } + catch (const Exception&) + { + } + } + } + else + { + Reference xQSupplier(xConnection, UNO_QUERY); + if(xQSupplier.is()) + { + Reference xQueries = xQSupplier->getQueries(); + OSL_ENSURE(xQueries->hasByName(sTableName), "table not available anymore?"); + try + { + Any aQuery = xQueries->getByName(sTableName); + Reference xPropSet; + aQuery >>= xPropSet; + xColsSupplier.set(xPropSet, UNO_QUERY); + } + catch (const Exception&) + { + } + } + } + + if(xColsSupplier.is()) + { + Reference 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 (!pImpl->GetContext()->hasByName(sSourceName)) + return true; + Reference xConnection = pImpl->GetConnection(sSourceName); + if (xConnection.is()) + { + Reference xTSupplier(xConnection, UNO_QUERY); + if(xTSupplier.is()) + { + Reference 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, &aImg, bShowColumns, nullptr); + } + } + + Reference xQSupplier(xConnection, UNO_QUERY); + if(xQSupplier.is()) + { + Reference 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, &aImg, bShowColumns, nullptr); + } + } + } + } + catch (const Exception&) + { + } + } + } + return true; +} + +OUString SwDBTreeList::GetDBName(OUString& rTableName, OUString& rColumnName, sal_Bool* pbIsTable) +{ + OUString sDBName; + std::unique_ptr 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(const OUString& rDBName, const OUString& rTableName, const OUString& rColumnName) +{ + std::unique_ptr xParent(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_iter_first(*xParent)) + return; + + do + { + if (rDBName == m_xTreeView->get_text(*xParent)) + { + if (!m_xTreeView->iter_has_child(*xParent)) + { + RequestingChildrenHdl(*xParent); + m_xTreeView->expand_row(*xParent); + } + std::unique_ptr xChild(m_xTreeView->make_iterator(xParent.get())); + if (!m_xTreeView->iter_children(*xChild)) + continue; + do + { + if (rTableName == m_xTreeView->get_text(*xChild)) + { + m_xTreeView->copy_iterator(*xChild, *xParent); + + bool bNoChild = false; + if (bShowColumns && !rColumnName.isEmpty()) + { + if (!m_xTreeView->iter_has_child(*xParent)) + { + 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) +{ + pImpl->SetWrtShell(rSh); + if (m_xTreeView->get_visible() && !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 != bShowColumns) + { + bShowColumns = bShowCol; + OUString sTableName; + OUString sColumnName; + const OUString sDBName(GetDBName(sTableName, sColumnName)); + + m_xTreeView->freeze(); + + std::unique_ptr xIter(m_xTreeView->make_iterator()); + std::unique_ptr 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 000000000..ad3b1c69a --- /dev/null +++ b/sw/source/uibase/dbui/dbui.cxx @@ -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 . + */ + +#include + +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_xDocName(m_xBuilder->weld_label("docname")) + , 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_sCountingPattern() + , 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("%Y"); + constexpr OUStringLiteral sVariable_Position("%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 000000000..10d8ea748 --- /dev/null +++ b/sw/source/uibase/dbui/maildispatcher.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include + +#include +#include + +using namespace ::com::sun::star; + +typedef std::vector< ::rtl::Reference > MailDispatcherListenerContainer_t; + +namespace /* private */ +{ + class MailDeliveryNotifier + { + public: + MailDeliveryNotifier(uno::Reference const & message) : + message_(message) + {} + + void operator() (::rtl::Reference const & listener) const + { listener->mailDelivered(message_); } + + private: + uno::Reference message_; + }; + + class MailDeliveryErrorNotifier + { + public: + MailDeliveryErrorNotifier( + ::rtl::Reference const & xMailDispatcher, + uno::Reference const & message, + const OUString& error_message) : + mail_dispatcher_(xMailDispatcher), + message_(message), + error_message_(error_message) + {} + + void operator() (::rtl::Reference const & listener) const + { listener->mailDeliveryError(mail_dispatcher_, message_, error_message_); } + + private: + ::rtl::Reference mail_dispatcher_; + uno::Reference message_; + OUString error_message_; + }; + +} // namespace private + +MailDispatcher::MailDispatcher(uno::Reference const & mailserver) : + m_xMailserver( 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 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 MailDispatcher::dequeueMailMessage() +{ + ::osl::MutexGuard guard( m_aMessageContainerMutex ); + uno::Reference 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 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 > MailDispatcher::cloneListener() +{ + ::osl::MutexGuard guard( m_aListenerContainerMutex ); + return m_aListenerVector; +} + +void MailDispatcher::sendMailMessageNotifyListener(uno::Reference 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 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 000000000..0981bce7f --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +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); + + 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 '@' + and for at least two characters before and after the dot +*/ +bool CheckMailAddress( const OUString& rMailAddress ) +{ + const sal_Int32 nPosAt = rMailAddress.indexOf('@'); + if (nPosAt<0 || rMailAddress.lastIndexOf('@')!=nPosAt) + return false; + const sal_Int32 nPosDot = rMailAddress.indexOf('.', nPosAt); + return !(nPosDot<0 || nPosDot-nPosAt<3 || rMailAddress.getLength()-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 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&) + { + OSL_FAIL("exception caught"); + } + 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 ) with the database content + //unassigned columns are expanded to + Reference< XColumnsSupplier > xColsSupp( rConfigItem.GetResultSet(), UNO_QUERY); + Reference xColAccess = xColsSupp.is() ? xColsSupp->getColumns() : nullptr; + Sequence< OUString> aAssignment = pAssignments ? + *pAssignments : + rConfigItem.GetColumnAssignment( + rConfigItem.GetCurrentDBData() ); + const OUString* pAssignment = aAssignment.getConstArray(); + const std::vector>& 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&) + { + OSL_FAIL("SQLException caught"); + } + } + } + else + { + aItem.sText = sNotAssigned; + } + + } + sAddress.append(aItem.sText); + } + return sAddress.makeStringAndClear(); +} + +SwAddressPreview::SwAddressPreview(std::unique_ptr xWindow) + : pImpl(new SwAddressPreview_Impl()) + , m_xVScrollBar(std::move(xWindow)) +{ + m_xVScrollBar->set_user_managed_scrolling(); + 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) +{ + pImpl->aAddresses.push_back(rAddress); + UpdateScrollBar(); +} + +void SwAddressPreview::SetAddress(const OUString& rAddress) +{ + pImpl->aAddresses.clear(); + pImpl->aAddresses.push_back(rAddress); + m_xVScrollBar->set_vpolicy(VclPolicyType::NEVER); + Invalidate(); +} + +sal_uInt16 SwAddressPreview::GetSelectedAddress()const +{ + OSL_ENSURE(pImpl->nSelectedAddress < pImpl->aAddresses.size(), "selection invalid"); + return pImpl->nSelectedAddress; +} + +void SwAddressPreview::SelectAddress(sal_uInt16 nSelect) +{ + OSL_ENSURE(pImpl->nSelectedAddress < pImpl->aAddresses.size(), "selection invalid"); + pImpl->nSelectedAddress = nSelect; + // now make it visible... + sal_uInt16 nSelectRow = nSelect / pImpl->nColumns; + sal_uInt16 nStartRow = m_xVScrollBar->vadjustment_get_value(); + if( (nSelectRow < nStartRow) || (nSelectRow >= (nStartRow + pImpl->nRows) )) + m_xVScrollBar->vadjustment_set_value(nSelectRow); +} + +void SwAddressPreview::Clear() +{ + pImpl->aAddresses.clear(); + pImpl->nSelectedAddress = 0; + UpdateScrollBar(); +} + +void SwAddressPreview::ReplaceSelectedAddress(const OUString& rNew) +{ + pImpl->aAddresses[pImpl->nSelectedAddress] = rNew; + Invalidate(); +} + +void SwAddressPreview::RemoveSelectedAddress() +{ + pImpl->aAddresses.erase(pImpl->aAddresses.begin() + pImpl->nSelectedAddress); + if(pImpl->nSelectedAddress) + --pImpl->nSelectedAddress; + UpdateScrollBar(); + Invalidate(); +} + +void SwAddressPreview::SetLayout(sal_uInt16 nRows, sal_uInt16 nColumns) +{ + pImpl->nRows = nRows; + pImpl->nColumns = nColumns; + UpdateScrollBar(); +} + +void SwAddressPreview::EnableScrollBar() +{ + pImpl->bEnableScrollBar = true; +} + +void SwAddressPreview::UpdateScrollBar() +{ + if (pImpl->nColumns) + { + sal_uInt16 nResultingRows = static_cast(pImpl->aAddresses.size() + pImpl->nColumns - 1) / pImpl->nColumns; + ++nResultingRows; + auto nValue = m_xVScrollBar->vadjustment_get_value(); + if (nValue > nResultingRows) + nValue = nResultingRows; + m_xVScrollBar->set_vpolicy(pImpl->bEnableScrollBar && nResultingRows > pImpl->nRows ? VclPolicyType::ALWAYS : VclPolicyType::NEVER); + m_xVScrollBar->vadjustment_configure(nValue, 0, nResultingRows, 1, 10, 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); + + if (vcl::Window* pDefaultDevice = dynamic_cast(Application::GetDefaultDevice())) + pDefaultDevice->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_vscroll_width()); + nStartRow = m_xVScrollBar->vadjustment_get_value(); + } + Size aPartSize(aSize.Width() / pImpl->nColumns, + aSize.Height() / pImpl->nRows); + aPartSize.AdjustWidth( -2 ); + aPartSize.AdjustHeight( -2 ); + + sal_uInt16 nAddress = nStartRow * pImpl->nColumns; + const sal_uInt16 nNumAddresses = static_cast(pImpl->aAddresses.size()); + for (sal_uInt16 nRow = 0; nRow < pImpl->nRows ; ++nRow) + { + for (sal_uInt16 nCol = 0; nCol < pImpl->nColumns; ++nCol) + { + if (nAddress >= nNumAddresses) + break; + Point aPos(nCol * aPartSize.Width(), + nRow * aPartSize.Height()); + aPos.Move(1, 1); + bool bIsSelected = nAddress == pImpl->nSelectedAddress; + if ((pImpl->nColumns * pImpl->nRows) == 1) + bIsSelected = false; + OUString adr(pImpl->aAddresses[nAddress]); + DrawText_Impl(rRenderContext, adr, aPos, aPartSize, bIsSelected); + ++nAddress; + } + } + rRenderContext.SetClipRegion(); +} + +bool SwAddressPreview::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (rMEvt.IsLeft() && pImpl->nRows && pImpl->nColumns) + { + //determine the selected address + const Point& rMousePos = rMEvt.GetPosPixel(); + Size aSize(GetOutputSizePixel()); + Size aPartSize( aSize.Width()/pImpl->nColumns, aSize.Height()/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 * pImpl->nColumns + nCol; + + if( nSelect < pImpl->aAddresses.size() && + pImpl->nSelectedAddress != static_cast(nSelect)) + { + pImpl->nSelectedAddress = static_cast(nSelect); + m_aSelectHdl.Call(nullptr); + } + Invalidate(); + } + return true; +} + +bool SwAddressPreview::KeyInput( const KeyEvent& rKEvt ) +{ + sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); + bool bHandled = false; + if (pImpl->nRows && pImpl->nColumns) + { + sal_uInt32 nSelectedRow = pImpl->nSelectedAddress / pImpl->nColumns; + sal_uInt32 nSelectedColumn = pImpl->nSelectedAddress - (nSelectedRow * pImpl->nColumns); + switch(nKey) + { + case KEY_UP: + if(nSelectedRow) + --nSelectedRow; + bHandled = true; + break; + case KEY_DOWN: + if(pImpl->aAddresses.size() > o3tl::make_unsigned(pImpl->nSelectedAddress + pImpl->nColumns)) + ++nSelectedRow; + bHandled = true; + break; + case KEY_LEFT: + if(nSelectedColumn) + --nSelectedColumn; + bHandled = true; + break; + case KEY_RIGHT: + if(nSelectedColumn < o3tl::make_unsigned(pImpl->nColumns - 1) && + pImpl->aAddresses.size() - 1 > pImpl->nSelectedAddress ) + ++nSelectedColumn; + bHandled = true; + break; + } + sal_uInt32 nSelect = nSelectedRow * pImpl->nColumns + nSelectedColumn; + if( nSelect < pImpl->aAddresses.size() && + pImpl->nSelectedAddress != static_cast(nSelect)) + { + pImpl->nSelectedAddress = static_cast(nSelect); + m_aSelectHdl.Call(nullptr); + Invalidate(); + } + } + return bHandled; +} + +void SwAddressPreview::DrawText_Impl(vcl::RenderContext& rRenderContext, const OUString& 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, rAddress.getToken(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(!sAddress.isEmpty()) + { + if(sAddress[0] == '<') + { + aRet.bIsColumn = true; + sal_Int32 nClose = sAddress.indexOf('>'); + OSL_ENSURE(nClose != -1, "closing '>' not found"); + if( nClose != -1 ) + { + aRet.sText = sAddress.copy(1, nClose - 1); + sAddress = sAddress.copy(nClose + 1); + } + else + { + aRet.sText = sAddress.copy(1, 1); + sAddress = sAddress.copy(1); + } + } + else + { + sal_Int32 nOpen = sAddress.indexOf('<'); + sal_Int32 nReturn = sAddress.indexOf('\n'); + if(nReturn == 0) + { + aRet.bIsReturn = true; + aRet.sText = "\n"; + sAddress = sAddress.copy(1); + } + else if(-1 == nOpen && -1 == nReturn) + { + aRet.sText = sAddress; + sAddress.clear(); + } + else + { + if (nOpen == -1) + nOpen = sAddress.getLength(); + if (nReturn == -1) + nReturn = sAddress.getLength(); + sal_Int32 nTarget = std::min(nOpen, nReturn); + aRet.sText = sAddress.copy(0, nTarget); + sAddress = 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( + const OUString& rMailServer, sal_Int16 nPort, + const OUString& rConnectionType) : + m_sMailServer(rMailServer), + m_nPort(nPort), + m_sConnectionType(rConnectionType) +{ +} + +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(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(const OUString& rBody, const OUString& rMimeType) : + cppu::WeakComponentImplHelper< datatransfer::XTransferable, beans::XPropertySet >(m_aMutex), + m_aMimeType( rMimeType ), + m_sBody( rBody ), + m_bIsBody( true ) +{ +} + +SwMailTransferable::SwMailTransferable(const OUString& rURL, + const OUString& rName, const OUString& rMimeType) : + cppu::WeakComponentImplHelper< datatransfer::XTransferable, beans::XPropertySet >(m_aMutex), + m_aMimeType( rMimeType ), + m_aURL(rURL), + m_aName( rName ), + m_bIsBody( false ) +{ +} + +SwMailTransferable::~SwMailTransferable() +{ +} + +uno::Any SwMailTransferable::getTransferData( const datatransfer::DataFlavor& /*aFlavor*/ ) +{ + uno::Any aRet; + if( m_bIsBody ) + aRet <<= m_sBody; + else + { + Sequence 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( ) +{ + uno::Sequence< datatransfer::DataFlavor > aRet(1); + aRet[0].MimeType = m_aMimeType; + if( m_bIsBody ) + { + aRet[0].DataType = cppu::UnoType::get(); + } + else + { + aRet[0].HumanPresentableName = m_aName; + aRet[0].DataType = cppu::UnoType>::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() : + cppu::WeakComponentImplHelper< mail::XMailMessage>(m_aMutex) +{ +} + +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[m_aRecipients.getLength() - 1] = rRecipientAddress; +} + +void SwMailMessage::addCcRecipient( const OUString& rRecipientAddress ) +{ + m_aCcRecipients.realloc(m_aCcRecipients.getLength() + 1); + m_aCcRecipients[m_aCcRecipients.getLength() - 1] = rRecipientAddress; + +} + +void SwMailMessage::addBccRecipient( const OUString& rRecipientAddress ) +{ + m_aBccRecipients.realloc(m_aBccRecipients.getLength() + 1); + m_aBccRecipients[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[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 000000000..e2cff7390 --- /dev/null +++ b/sw/source/uibase/dbui/mailmergetoolbarcontrols.cxx @@ -0,0 +1,422 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace css; + +namespace { + +class CurrentEdit final : public InterimItemWindow +{ +private: + std::unique_ptr 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")) + { + m_xWidget->connect_key_press(LINK(this, CurrentEdit, KeyInputHdl)); + SetSizePixel(m_xWidget->get_preferred_size()); + } + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + 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& 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. +class MMCurrentEntryController : public svt::ToolboxController, public lang::XServiceInfo +{ + VclPtr m_xCurrentEdit; + + DECL_LINK(CurrentEditUpdatedHdl, weld::Entry&, bool); + +public: + explicit MMCurrentEntryController(const uno::Reference& rContext) + : svt::ToolboxController(rContext, uno::Reference(), ".uno:MailMergeCurrentEntry") + , m_xCurrentEdit(nullptr) + { + } + + // XInterface + virtual uno::Any SAL_CALL queryInterface(const uno::Type& aType) override + { + uno::Any a(ToolboxController::queryInterface(aType)); + if (a.hasValue()) + return a; + + return ::cppu::queryInterface(aType, static_cast(this)); + } + + void SAL_CALL acquire() throw () override + { + ToolboxController::acquire(); + } + + void SAL_CALL release() throw () override + { + ToolboxController::release(); + } + + // 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 SAL_CALL getSupportedServiceNames() override + { + return { "com.sun.star.frame.ToolbarController" }; + } + + // XComponent + virtual void SAL_CALL dispose() override; + + // XToolbarController + virtual uno::Reference SAL_CALL createItemWindow(const uno::Reference& rParent) override; + + // XStatusListener + virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) override; +}; + +class ExcludeCheckBox final : public InterimItemWindow +{ +private: + std::unique_ptr 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")) + { + 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(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + 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& 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. +class MMExcludeEntryController : public svt::ToolboxController, public lang::XServiceInfo +{ + VclPtr m_xExcludeCheckbox; + + DECL_STATIC_LINK(MMExcludeEntryController, ExcludeHdl, weld::ToggleButton&, void); + +public: + explicit MMExcludeEntryController(const uno::Reference& rContext) + : svt::ToolboxController(rContext, uno::Reference(), ".uno:MailMergeExcludeEntry") + , m_xExcludeCheckbox(nullptr) + { + } + + // XInterface + virtual uno::Any SAL_CALL queryInterface(const uno::Type& aType) override + { + uno::Any a(ToolboxController::queryInterface(aType)); + if (a.hasValue()) + return a; + + return ::cppu::queryInterface(aType, static_cast(this)); + } + + void SAL_CALL acquire() throw () override + { + ToolboxController::acquire(); + } + + void SAL_CALL release() throw () override + { + ToolboxController::release(); + } + + // 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 SAL_CALL getSupportedServiceNames() override + { + return { "com.sun.star.frame.ToolbarController" }; + } + + // XComponent + virtual void SAL_CALL dispose() override; + + // XToolbarController + virtual uno::Reference SAL_CALL createItemWindow(const uno::Reference& 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 MMCurrentEntryController::createItemWindow(const uno::Reference& rParent) +{ + VclPtr pParent = VCLUnoHelper::GetWindow(rParent); + ToolBox* pToolbar = dynamic_cast(pParent.get()); + if (pToolbar) + { + // make it visible + m_xCurrentEdit = VclPtr::Create(pToolbar); + m_xCurrentEdit->connect_activate(LINK(this, MMCurrentEntryController, CurrentEditUpdatedHdl)); + } + + return VCLUnoHelper::GetInterface(m_xCurrentEdit); +} + +IMPL_LINK(MMCurrentEntryController, CurrentEditUpdatedHdl, weld::Entry&, rEdit, bool) +{ + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + 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()); + } + return true; +}; + +void MMCurrentEntryController::statusChanged(const frame::FeatureStateEvent& rEvent) +{ + if (!m_xCurrentEdit) + return; + + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + 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 MMExcludeEntryController::createItemWindow(const uno::Reference& rParent) +{ + VclPtr pParent = VCLUnoHelper::GetWindow(rParent); + ToolBox* pToolbar = dynamic_cast(pParent.get()); + if (pToolbar) + { + // make it visible + m_xExcludeCheckbox = VclPtr::Create(pToolbar); + m_xExcludeCheckbox->connect_toggled(LINK(this, MMExcludeEntryController, ExcludeHdl)); + } + + return VCLUnoHelper::GetInterface(m_xExcludeCheckbox); +} + +IMPL_STATIC_LINK(MMExcludeEntryController, ExcludeHdl, weld::ToggleButton&, rCheckbox, void) +{ + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + xConfigItem = pView->GetMailMergeConfigItem(); + + if (xConfigItem) + xConfigItem->ExcludeRecord(xConfigItem->GetResultSetPosition(), rCheckbox.get_active()); +}; + +void MMExcludeEntryController::statusChanged(const frame::FeatureStateEvent& rEvent) +{ + if (!m_xExcludeCheckbox) + return; + + SwView* pView = ::GetActiveView(); + std::shared_ptr xConfigItem; + if (pView) + xConfigItem = pView->GetMailMergeConfigItem(); + + if (!xConfigItem || !rEvent.IsEnabled) + { + m_xExcludeCheckbox->set_sensitive(false); + m_xExcludeCheckbox->set_active(false); + } + else + { + m_xExcludeCheckbox->set_sensitive(false); + 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 const &) +{ + return cppu::acquire(new MMCurrentEntryController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface * +lo_writer_MMExcludeEntryController_get_implementation( + uno::XComponentContext *context, + uno::Sequence 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 000000000..84cb67742 --- /dev/null +++ b/sw/source/uibase/dbui/mmconfigitem.cxx @@ -0,0 +1,1711 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + +const char cAddressDataAssignments[] = "AddressDataAssignments"; +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 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> 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 (size_t i = 0; i < SAL_N_ELEMENTS(SA_ADDRESS_HEADER); ++i) + { + m_AddressHeaderSA.emplace_back(SwResId(SA_ADDRESS_HEADER[i].first), SA_ADDRESS_HEADER[i].second); + } + + const Sequence& rNames = GetPropertyNames(); + Sequence 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; + } + } + } + //read the list of data base assignments + Sequence 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 = OUStringLiteral(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 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()) + { + uno::Sequence< OUString > aTempDocuments(m_aSavedDocuments.getLength()); + OUString* pTempDocuments = std::copy_if(m_aSavedDocuments.begin(), m_aSavedDocuments.end(), aTempDocuments.begin(), + [](const OUString& rDoc) { return SWUnoHelper::UCB_IsFile( rDoc ); }); + sal_Int32 nIndex = static_cast(std::distance(aTempDocuments.begin(), pTempDocuments)); + if(nIndex < m_aSavedDocuments.getLength()) + { + m_aSavedDocuments = aTempDocuments; + m_aSavedDocuments.realloc(nIndex); + } + } +} + +void SwMailMergeConfigItem_Impl::SetCurrentAddressBlockIndex( sal_Int32 nSet ) +{ + if(m_aAddressBlocks.size() >= sal::static_int_cast(nSet)) + { + m_nCurrentAddressBlock = nSet; + SetModified(); + } +} + +static OUString lcl_CreateNodeName(Sequence& 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>& 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>& 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& SwMailMergeConfigItem_Impl::GetPropertyNames() +{ + static Sequence 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 aNames = GetPropertyNames(); + Sequence 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] <<= static_cast(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 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(4); + PropertyValue* pNewValues = aNewValues.getArray(); + pNewValues[0].Name = sNodePath; + pNewValues[0].Name += cDataSourceName; + pNewValues[0].Value <<= rAssignment.aDBData.sDataSource; + pNewValues[1].Name = sNodePath; + pNewValues[1].Name += cDataTableName; + pNewValues[1].Value <<= rAssignment.aDBData.sCommand; + pNewValues[2].Name = sNodePath; + pNewValues[2].Name += cDataCommandType; + pNewValues[2].Value <<= rAssignment.aDBData.nCommandType; + pNewValues[3].Name = sNodePath; + pNewValues[3].Name += cDBColumnAssignments; + pNewValues[3].Value <<= 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.begin(), + [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.begin(), + [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_pSourceView(nullptr), + m_pTargetView(nullptr) +{ +} + +void SwMailMergeConfigItem::stopDBChangeListening() +{ + if (m_xDBChangedListener.is()) + { + uno::Reference xSupplier = m_pSourceView->GetUNOObject(); + xSupplier->removeSelectionChangeListener(m_xDBChangedListener); + m_xDBChangedListener.clear(); + } +} + +void SwMailMergeConfigItem::updateCurrentDBDataFromDocument() +{ + const SwDBData& rDBData = m_pSourceView->GetWrtShell().GetDBDesc(); + SetCurrentDBData(rDBData); +} + +SwMailMergeConfigItem::~SwMailMergeConfigItem() +{ + stopDBChangeListening(); +} + +void SwMailMergeConfigItem::Commit() +{ + if(m_pImpl->IsModified()) + m_pImpl->Commit(); +} + +const std::vector>& 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( xMgr->createInstance("com.sun.star.sdb.RowSet"), UNO_QUERY ); + Reference xRowProperties(xRowSet, UNO_QUERY); + xRowProperties->setPropertyValue("DataSourceName", makeAny(m_pImpl->m_aDBData.sDataSource)); + xRowProperties->setPropertyValue("Command", makeAny(m_pImpl->m_aDBData.sCommand)); + xRowProperties->setPropertyValue("CommandType", makeAny(m_pImpl->m_aDBData.nCommandType)); + xRowProperties->setPropertyValue("FetchSize", makeAny(sal_Int32(10))); + xRowProperties->setPropertyValue("ActiveConnection", makeAny(m_pImpl->m_xConnection.getTyped())); + try + { + xRowProperties->setPropertyValue("ApplyFilter", makeAny(!m_pImpl->m_sFilter.isEmpty())); + xRowProperties->setPropertyValue("Filter", makeAny(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) + { + m_pImpl->m_sFilter = rFilter; + m_pImpl->SetModified(); + Reference xRowProperties(m_pImpl->m_xResultSet, UNO_QUERY); + if(xRowProperties.is()) + { + try + { + xRowProperties->setPropertyValue("ApplyFilter", makeAny(!m_pImpl->m_sFilter.isEmpty())); + xRowProperties->setPropertyValue("Filter", makeAny(m_pImpl->m_sFilter)); + uno::Reference 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::IsRecordExcluded(sal_Int32 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 SwMailMergeConfigItem::GetSelection() const +{ + if(!m_pImpl->m_xResultSet.is()) + GetResultSet(); + if(!m_pImpl->m_xResultSet.is()) + return {}; + m_pImpl->m_xResultSet->last(); + sal_Int32 nResultSetSize = m_pImpl->m_xResultSet->getRow()+1; + std::vector vResult; + vResult.reserve(nResultSetSize); + for(sal_Int32 nIdx=1; nIdx(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 xCols = xColsSupp->getColumns(); + + const std::vector>& 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>& rHeaders = GetDefaultAddressHeaders(); + uno::Reference 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; + break; + 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; + break; + 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 ); + while(pViewShell) + { + if(pViewShell == pView) + return pView; + + pViewShell = SfxViewShell::GetNext( *pViewShell, false, checkSfxViewShell ); + } + 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 +{ + 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 xSupplier = m_pSourceView->GetUNOObject(); + xSupplier->removeSelectionChangeListener(m_xDBChangedListener); + m_xDBChangedListener.clear(); + } + + m_pSourceView = pView; + + if (!m_pSourceView) + return; + + std::vector aDBNameList; + std::vector 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 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 000000000..cd19c9a39 --- /dev/null +++ b/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx @@ -0,0 +1,827 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + pOtherCursor; // position where the spelling inside the _other_ area started + bool m_bDrawingsSpelled; // all drawings spelled + Reference 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 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 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 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) + { + 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) + { + 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->GetNode() || + m_pSpellState->m_pMarkNode != &pCursor->GetNode(false)|| + m_pSpellState->m_nPointPos != pCursor->GetPoint()->nContent.GetIndex()|| + m_pSpellState->m_nMarkPos != pCursor->GetMark()->nContent.GetIndex()) + 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->GetNode(); + m_pSpellState->m_pMarkNode = &pCursor->GetNode(false); + m_pSpellState->m_nPointPos = pCursor->GetPoint()->nContent.GetIndex(); + m_pSpellState->m_nMarkPos = pCursor->GetMark()->nContent.GetIndex(); + + } + 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(dynamic_cast< const SwView *>( pShell ) != nullptr) + { + pView = static_cast(pShell); + 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(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 = dynamic_cast( 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::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 ); + + std::unique_ptr pOutlView( new OutlinerView( &aTmpOutliner, &(rView.GetEditWin()) ) ); + pOutlView->GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) ); + aTmpOutliner.InsertView( pOutlView.get() ); + Size aSize(1,1); + tools::Rectangle aRect( Point(), aSize ); + pOutlView->SetOutputArea( aRect ); + aTmpOutliner.SetText( *pParaObj ); + aTmpOutliner.ClearModifyFlag(); + bHasSpellError = EESpellState::Ok != aTmpOutliner.HasSpellErrors(); + aTmpOutliner.RemoveView( pOutlView.get() ); + } + if(bHasSpellError) + { + // now the current one has to be deselected + if(pCurrentTextObj) + pDrView->SdrEndTextEdit( true ); + // and the found one should be activated + rSh.MakeVisible(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 000000000..45cc86b4f --- /dev/null +++ b/sw/source/uibase/dialog/regionsw.cxx @@ -0,0 +1,209 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void SwBaseShell::InsertRegionDialog(SfxRequest& rReq) +{ + SwWrtShell& rSh = GetShell(); + const SfxItemSet *pSet = rReq.GetArgs(); + + SfxItemSet aSet( + GetPool(), + svl::Items< + 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>{}); + + if (!pSet || pSet->Count()==0) + { + SwRect aRect; + rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + + 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 aTabDlg(pFact->CreateInsertSectionTabDialog( + GetView().GetFrameWeld(), aSet , rSh)); + aTabDlg->StartExecuteAsync([aTabDlg](sal_Int32 /*nResult*/){ + aTabDlg->disposeOnce(); + }); + rReq.Ignore(); + } + else + { + const SfxPoolItem *pItem = nullptr; + OUString aTmpStr; + if ( SfxItemState::SET == + pSet->GetItemState(FN_PARAM_REGION_NAME, true, &pItem) ) + { + const OUString sRemoveWhenUniStringIsGone = static_cast(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 ); + if(SfxItemState::SET == pSet->GetItemState(SID_ATTR_COLUMNS, false, &pItem)|| + SfxItemState::SET == pSet->GetItemState(FN_INSERT_REGION, false, &pItem)) + { + SwFormatCol aCol; + SwRect aRect; + rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + long nWidth = aRect.Width(); + + sal_uInt16 nCol = static_cast(pItem)->GetValue(); + if(nCol) + { + aCol.Init( nCol, 0, static_cast< sal_uInt16 >(nWidth) ); + aSet.Put(aCol); + } + } + else if(SfxItemState::SET == pSet->GetItemState(RES_COL, false, &pItem)) + { + aSet.Put(*pItem); + } + + const bool bHidden = SfxItemState::SET == pSet->GetItemState(FN_PARAM_REGION_HIDDEN, true, &pItem) && + static_cast(pItem)->GetValue(); + const bool bProtect = SfxItemState::SET == pSet->GetItemState(FN_PARAM_REGION_PROTECT, true, &pItem) && + static_cast(pItem)->GetValue(); + // #114856# edit in readonly sections + const bool bEditInReadonly = SfxItemState::SET == pSet->GetItemState(FN_PARAM_REGION_EDIT_IN_READONLY, true, &pItem) && + static_cast(pItem)->GetValue(); + + aSection.SetProtectFlag(bProtect); + aSection.SetHidden(bHidden); + // #114856# edit in readonly sections + aSection.SetEditInReadonlyFlag(bEditInReadonly); + + if(SfxItemState::SET == + pSet->GetItemState(FN_PARAM_REGION_CONDITION, true, &pItem)) + aSection.SetCondition(static_cast(pItem)->GetValue()); + + OUString aFile, aSub; + if(SfxItemState::SET == + pSet->GetItemState(FN_PARAM_1, true, &pItem)) + aFile = static_cast(pItem)->GetValue(); + + if(SfxItemState::SET == + pSet->GetItemState(FN_PARAM_3, true, &pItem)) + aSub = static_cast(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(pItem)->GetValue()); + } + + sLinkFileName += aSub; + aSection.SetType( SectionType::FileLink ); + aSection.SetLinkFileName(sLinkFileName); + } + rSh.InsertSection(aSection, aSet.Count() ? &aSet : nullptr); + rReq.Done(); + } +} + +void SwWrtShell::StartInsertRegionDialog(const SwSectionData& rSectionData) +{ + SfxItemSet aSet( + GetView().GetPool(), + svl::Items< + 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>{}); + SwRect aRect; + CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + 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 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 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 000000000..f726a8274 --- /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 + +#include + +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 const OUString sLibName(SWUI_DLL_NAME); + if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, sLibName, + SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ) ) + fp = reinterpret_cast( + 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 000000000..ad88e205e --- /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 +#include + +SwWrtShellItem::SwWrtShellItem( SwWrtShell* pSh ) + : SfxPoolItem( SID_WRT_SHELL ), pWrtSh( pSh ) +{ + +} + +bool SwWrtShellItem::operator==( const SfxPoolItem& rItem) const +{ + return SfxPoolItem::operator==(rItem) + && pWrtSh == static_cast(rItem).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 000000000..d558d0c6d --- /dev/null +++ b/sw/source/uibase/dialog/watermarkdialog.cxx @@ -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/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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"), m_xDialog.get())) +{ + InitFields(); +} + +SwWatermarkDialog::~SwWatermarkDialog() +{ +} + +void SwWatermarkDialog::InitFields() +{ + // Update font list + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + const SfxPoolItem* pFontItem; + const FontList* pFontList = nullptr; + std::unique_ptr xFontList; + + if ( pDocSh && ( ( pFontItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST ) ) != nullptr ) ) + pFontList = static_cast( 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 + const SfxPoolItem* pItem; + SfxItemState eState = m_rBindings.GetDispatcher()->QueryState( SID_WATERMARK, pItem ); + + if( eState >= SfxItemState::DEFAULT && pItem && pItem->Which() == SID_WATERMARK) + { + const SfxWatermarkItem* pWatermark = static_cast( pItem ); + 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 aPropertyValues( comphelper::InitPropertySequence( + { + { "Text", css::uno::makeAny( sText ) }, + { "Font", css::uno::makeAny( m_xFont->get_active_text() ) }, + { "Angle", css::uno::makeAny( static_cast( m_xAngle->get_value(FieldUnit::DEGREE) ) ) }, + { "Transparency", css::uno::makeAny( static_cast( m_xTransparency->get_value(FieldUnit::PERCENT) ) ) }, + { "Color", css::uno::makeAny( static_cast( 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 000000000..e1a6c99a9 --- /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 +#include +#include + +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(); + xAbstDlg.reset(pFact->CreateSwWordCountDialog(pBindings, this, pParentWindow->GetFrameWeld(), pInfo)); + SetController(xAbstDlg->GetController()); +} + +SwWordCountWrapper::~SwWordCountWrapper() +{ + xAbstDlg.disposeAndClear(); +} + +SfxChildWinInfo SwWordCountWrapper::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); + return aInfo; +} + +void SwWordCountWrapper::UpdateCounts() +{ + xAbstDlg->UpdateCounts(); +} + +void SwWordCountWrapper::SetCounts(const SwDocStat &rCurrCnt, const SwDocStat &rDocStat) +{ + 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 000000000..860a926a5 --- /dev/null +++ b/sw/source/uibase/dochdl/gloshdl.cxx @@ -0,0 +1,699 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +const short RET_EDIT = 100; + +namespace { + +struct TextBlockInfo_Impl +{ + OUString sTitle; + OUString sLongName; + OUString sGroupName; + TextBlockInfo_Impl(OUString const& rTitle, OUString const& rLongName, OUString const& rGroupName) + : sTitle(rTitle), sLongName(rLongName), sGroupName(rGroupName) {} +}; + +} + +// Dialog for edit templates +void SwGlossaryHdl::GlossaryDlg() +{ + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateGlossaryDlg(pViewFrame, this, pWrtShell)); + OUString sName; + OUString sShortName; + + if( RET_EDIT == pDlg->Execute() ) + { + sName = pDlg->GetCurrGrpName(); + sShortName = pDlg->GetCurrShortName(); + } + + pDlg.disposeAndClear(); + pCurGrp.reset(); + if(HasGlossaryList()) + { + GetGlossaryList()->ClearGroups(); + } + + if( !sName.isEmpty() || !sShortName.isEmpty() ) + 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(pCurGrp) + { + bool bPathEqual = false; + if(!bAlwaysCreateNew) + { + INetURLObject aTemp( pCurGrp->GetFileName() ); + const OUString sCurBase = aTemp.getBase(); + aTemp.removeSegment(); + const OUString sCurEntryPath = aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE); + const std::vector & rPathArr = rStatGlossaries.GetPathArray(); + sal_uInt16 nCurrentPath = USHRT_MAX; + for (size_t nPath = 0; nPath < rPathArr.size(); ++nPath) + { + if (sCurEntryPath == rPathArr[nPath]) + { + nCurrentPath = static_cast(nPath); + break; + } + } + const OUString sPath = sGroup.getToken(1, GLOS_DELIM); + sal_uInt16 nComparePath = static_cast(sPath.toInt32()); + if(nCurrentPath == nComparePath && + sGroup.getToken(0, GLOS_DELIM) == sCurBase) + bPathEqual = true; + } + + // When path changed, the name is not reliable + if(!bAlwaysCreateNew && bPathEqual) + return; + } + aCurGrp = sGroup; + if(!bApi) + { + pCurGrp = rStatGlossaries.GetGroupDoc(aCurGrp, true); + } +} + +size_t SwGlossaryHdl::GetGroupCnt() const +{ + return rStatGlossaries.GetGroupCnt(); +} + +OUString SwGlossaryHdl::GetGroupName( size_t nId, OUString* pTitle ) +{ + OUString sRet = rStatGlossaries.GetGroupName(nId); + if(pTitle) + { + std::unique_ptr pGroup = 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); + 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 pGroup = rStatGlossaries.GetGroupDoc(sOldGroup); + if(pGroup) + { + pGroup->SetName(rNewTitle); + } + } + else + { + OUString sNewGroup(rNew); + if (sNewGroup.indexOf(GLOS_DELIM)<0) + { + sNewGroup += OUStringChar(GLOS_DELIM) + "0"; + } + rStatGlossaries.RenameGroupDoc(sOldGroup, sNewGroup, rNewTitle); + rNew = sNewGroup; + } +} + +// delete an autotext-file-group +bool SwGlossaryHdl::DelGroup(const OUString &rGrpName) +{ + OUString sGroup(rGrpName); + if (sGroup.indexOf(GLOS_DELIM)<0) + FindGroupName(sGroup); + if( rStatGlossaries.DelGroupDoc(sGroup) ) + { + if(pCurGrp) + { + if (pCurGrp->GetName() == sGroup) + pCurGrp.reset(); + } + return true; + } + return false; +} + +// ask for number of autotexts +sal_uInt16 SwGlossaryHdl::GetGlossaryCnt() const +{ + return pCurGrp ? pCurGrp->GetCount() : 0; +} + +OUString SwGlossaryHdl::GetGlossaryName( sal_uInt16 nId ) +{ + OSL_ENSURE(nId < GetGlossaryCnt(), "Text building block array over-indexed."); + return pCurGrp->GetLongName( nId ); +} + +OUString SwGlossaryHdl::GetGlossaryShortName(sal_uInt16 nId) +{ + OSL_ENSURE(nId < GetGlossaryCnt(), "Text building block array over-indexed."); + return pCurGrp->GetShortName( nId ); +} + +// ask for short name +OUString SwGlossaryHdl::GetGlossaryShortName(const OUString &rName) +{ + OUString sReturn; + SwTextBlocks *pTmp = + pCurGrp ? pCurGrp.get() : rStatGlossaries.GetGroupDoc( aCurGrp ).release(); + if(pTmp) + { + sal_uInt16 nIdx = pTmp->GetLongIndex( rName ); + if( nIdx != sal_uInt16(-1) ) + sReturn = pTmp->GetShortName( nIdx ); + if( !pCurGrp ) + delete pTmp; + } + return sReturn; +} + +// short name for autotext already used? +bool SwGlossaryHdl::HasShortName(const OUString& rShortName) const +{ + SwTextBlocks *pBlock = pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc( aCurGrp ).release(); + bool bRet = pBlock->GetIndex( rShortName ) != sal_uInt16(-1); + if( !pCurGrp ) + delete pBlock; + return bRet; +} + +// Create autotext +bool SwGlossaryHdl::NewGlossary(const OUString& rName, const OUString& rShortName, + bool bCreateGroup, bool bNoAttr) +{ + SwTextBlocks *pTmp = + pCurGrp ? pCurGrp.get() : rStatGlossaries.GetGroupDoc( aCurGrp, bCreateGroup ).release(); + //pTmp == 0 if the AutoText path setting is wrong + if(!pTmp) + { + if (!pCurGrp) + delete pTmp; + return false; + } + + OUString sOnlyText; + OUString* pOnlyText = nullptr; + if( bNoAttr ) + { + pWrtShell->GetSelectedText( sOnlyText, ParaBreakType::ToOnlyCR ); + pOnlyText = &sOnlyText; + } + + const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + + const sal_uInt16 nSuccess = pWrtShell->MakeGlossary( *pTmp, rName, rShortName, + rCfg.IsSaveRelFile(), pOnlyText ); + if(nSuccess == sal_uInt16(-1) ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(pWrtShell->GetView().GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, SwResId(STR_ERR_INSERT_GLOS))); + xBox->run(); + } + if( !pCurGrp ) + delete pTmp; + return nSuccess != sal_uInt16(-1); +} + +// Delete an autotext +bool SwGlossaryHdl::DelGlossary(const OUString &rShortName) +{ + SwTextBlocks *pGlossary = pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc(aCurGrp).release(); + //pTmp == 0 if the AutoText path setting is wrong + if(!pGlossary) + { + if( !pCurGrp ) + delete pGlossary; + return false; + } + + sal_uInt16 nIdx = pGlossary->GetIndex( rShortName ); + if( nIdx != sal_uInt16(-1) ) + pGlossary->Delete( nIdx ); + if( !pCurGrp ) + delete pGlossary; + return true; +} + +// expand short name +bool SwGlossaryHdl::ExpandGlossary(weld::Window* pParent) +{ + OSL_ENSURE(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 pGlossary = rStatGlossaries.GetGroupDoc(sGroupName); + + OUString aShortName; + + // use this at text selection + if(pWrtShell->SwCursorShell::HasSelection() && !pWrtShell->IsBlockMode()) + { + aShortName = pWrtShell->GetSelText(); + } + else + { + if(pWrtShell->IsAddMode()) + pWrtShell->LeaveAddMode(); + else if(pWrtShell->IsBlockMode()) + pWrtShell->LeaveBlockMode(); + else if(pWrtShell->IsExtMode()) + pWrtShell->LeaveExtMode(); + // select word (tdf#126589: part to the left of cursor) + if (pWrtShell->IsInWord() || pWrtShell->IsEndWrd()) + pWrtShell->PrvWrd(true); + // ask for word + if(pWrtShell->IsSelection()) + aShortName = pWrtShell->GetSelText(); + } + return pGlossary && Expand(pParent, aShortName, &rStatGlossaries, std::move(pGlossary)); +} + +bool SwGlossaryHdl::Expand(weld::Window* pParent, const OUString& rShortName, + SwGlossaries *pGlossaries, + std::unique_ptr pGlossary) +{ + std::vector 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 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(pWrtShell->IsSelection() && aShortName.getLength() > nMaxLen) + { + aShortName = aShortName.copy(0, nMaxLen) + " ..."; + } + OUString aTmp( SwResId(STR_NOGLOS)); + aTmp = aTmp.replaceFirst("%1", aShortName); + std::unique_ptr xInfoBox(Application::CreateMessageDialog(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 + pWrtShell->StartUndo(SwUndoId::INSGLOSSARY); + if( aStartMacro.HasMacro() ) + pWrtShell->ExecMacro( aStartMacro ); + if(pWrtShell->HasSelection()) + pWrtShell->DelLeft(); + pWrtShell->StartAllAction(); + + // cache all InputFields + SwInputFieldList aFieldLst( pWrtShell, true ); + + pWrtShell->InsertGlossary(*pGlossary, aShortName); + pWrtShell->EndAllAction(); + if( aEndMacro.HasMacro() ) + { + pWrtShell->ExecMacro( aEndMacro ); + } + pWrtShell->EndUndo(SwUndoId::INSGLOSSARY); + + // demand input for all new InputFields + if( aFieldLst.BuildSortLst() ) + pWrtShell->UpdateInputFields( &aFieldLst ); + } + return true; +} + +// add autotext +bool SwGlossaryHdl::InsertGlossary(const OUString &rName) +{ + OSL_ENSURE(pWrtShell->CanInsert(), "illegal"); + + SwTextBlocks *pGlos = + pCurGrp ? pCurGrp.get() : rStatGlossaries.GetGroupDoc(aCurGrp).release(); + + if (!pGlos) + { + if (!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() ) + pWrtShell->ExecMacro( aStartMacro ); + if( pWrtShell->HasSelection() ) + pWrtShell->DelRight(); + pWrtShell->StartAllAction(); + + // cache all InputFields + SwInputFieldList aFieldLst( pWrtShell, true ); + + pWrtShell->InsertGlossary(*pGlos, rName); + pWrtShell->EndAllAction(); + if( aEndMacro.HasMacro() ) + { + pWrtShell->ExecMacro( aEndMacro ); + } + + // demand input for all new InputFields + if( aFieldLst.BuildSortLst() ) + pWrtShell->UpdateInputFields( &aFieldLst ); + + if(!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 : + pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc( 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(!pCurGrp && !pGlossary) + delete pGlos; +} + +void SwGlossaryHdl::GetMacros( const OUString &rShortName, + SvxMacro& rStart, + SvxMacro& rEnd, + SwTextBlocks *pGlossary ) +{ + SwTextBlocks *pGlos = pGlossary ? pGlossary + : pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc(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( !pCurGrp && !pGlossary ) + delete pGlos; +} + +// ctor, dtor +SwGlossaryHdl::SwGlossaryHdl(SfxViewFrame* pVwFrame, SwWrtShell *pSh) + : rStatGlossaries( *::GetGlossaries() ), + aCurGrp( SwGlossaries::GetDefName() ), + pViewFrame( pVwFrame ), + pWrtShell( pSh ) +{ +} + +SwGlossaryHdl::~SwGlossaryHdl() +{ +} + +// rename an autotext +bool SwGlossaryHdl::Rename(const OUString& rOldShort, const OUString& rNewShortName, + const OUString& rNewName ) +{ + bool bRet = false; + SwTextBlocks *pGlossary = pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc(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( !pCurGrp ) + delete pGlossary; + } + return bRet; +} + +bool SwGlossaryHdl::IsReadOnly( const OUString* pGrpNm ) const +{ + SwTextBlocks *pGlossary = nullptr; + + if (pGrpNm) + pGlossary = rStatGlossaries.GetGroupDoc( *pGrpNm ).release(); + else if (pCurGrp) + pGlossary = pCurGrp.get(); + else + pGlossary = rStatGlossaries.GetGroupDoc(aCurGrp).release(); + + const bool bRet = !pGlossary || pGlossary->IsReadOnly(); + if( pGrpNm || !pCurGrp ) + delete pGlossary; + return bRet; +} + +bool SwGlossaryHdl::IsOld() const +{ + if( !pCurGrp ) + rStatGlossaries.GetGroupDoc(aCurGrp).reset(); + return false; +} + +// find group without path index +bool SwGlossaryHdl::FindGroupName(OUString& rGroup) +{ + return rStatGlossaries.FindGroupName(rGroup); +} + +bool SwGlossaryHdl::CopyToClipboard(SwWrtShell& rSh, const OUString& rShortName) +{ + SwTextBlocks *pGlossary = pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc(aCurGrp).release(); + + rtl::Reference pTransfer = new SwTransferable( rSh ); + + bool bRet = pTransfer->CopyGlossary( *pGlossary, rShortName ); + if( !pCurGrp ) + delete pGlossary; + return bRet; +} + +bool SwGlossaryHdl::ImportGlossaries( const OUString& rName ) +{ + bool bRet = false; + if( !rName.isEmpty() ) + { + std::shared_ptr pFilter; + std::unique_ptr pMed(new SfxMedium( rName, StreamMode::READ, nullptr, nullptr )); + SfxFilterMatcher aMatcher( "swriter" ); + pMed->UseInteractionHandler( true ); + if (!aMatcher.GuessFilter(*pMed, pFilter, SfxFilterFlags::NONE)) + { + SwTextBlocks *pGlossary = nullptr; + pMed->SetFilter( pFilter ); + Reader* pR = SwReaderWriter::GetReader( pFilter->GetUserData() ); + if( pR && nullptr != ( pGlossary = pCurGrp ? pCurGrp.get() + : rStatGlossaries.GetGroupDoc(aCurGrp).release()) ) + { + SwReader aReader( *pMed, rName ); + if( aReader.HasGlossaries( *pR ) ) + { + const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + bRet = aReader.ReadGlossaries( *pR, *pGlossary, + rCfg.IsSaveRelFile() ); + } + + if (!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 000000000..b4e91dcec --- /dev/null +++ b/sw/source/uibase/dochdl/swdtflvr.cxx @@ -0,0 +1,4349 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define OLESIZE 11905 - 2 * lMinBorder, 6 * MM50 + +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); +} + +} + +#define DDE_TXT_ENCODING osl_getThreadTextEncoding() + +namespace { + +class SwTransferDdeLink : public ::sfx2::SvBaseLink +{ + OUString sName; + ::sfx2::SvLinkSourceRef refObj; + SwTransferable& rTrnsfr; + SwDocShell* pDocShell; + sal_uLong nOldTimeOut; + bool bDelBookmrk : 1; + bool 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::unique_ptr m_pPaM; + 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 ) +{ + rSh.GetView().AddTransferable(*this); + SwDocShell* pDShell = rSh.GetDoc()->GetDocShell(); + if( pDShell ) + { + 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! + if( m_xDdeLink.is() ) + { + static_cast( m_xDdeLink.get() )->Disconnect( true ); + m_xDdeLink.clear(); + } + + 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(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 *const pDoc = rDocFac.GetDoc(); + OSL_ENSURE( pDoc, "Document not found" ); + if (pDoc) + { + pDoc->SetClipBoard( true ); + } + return pDoc; +} + +void SwTransferable::ObjectReleased() +{ + SwModule *pMod = SW_MOD(); + 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( OLESIZE ); + 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 aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() ); + for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) + if( SwNodeType::Ole == pNd->GetNodeType() ) + { + xObj = static_cast(pNd)->GetOLEObj().GetOleRef(); + nAspect = static_cast(pNd)->GetAspect(); + break; + } + } + return xObj; +} + +const Graphic* SwTransferable::FindOLEReplacementGraphic() const +{ + if( m_pClpDocFac ) + { + SwIterator aIter( *m_pClpDocFac->GetDoc()->GetDfltGrfFormatColl() ); + for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) + if( SwNodeType::Ole == pNd->GetNodeType() ) + { + return static_cast(pNd)->GetGraphic(); + } + } + + return nullptr; +} + +void SwTransferable::RemoveDDELinkFormat( const vcl::Window& rWin ) +{ + RemoveFormat( SotClipboardFormatId::LINK ); + CopyToClipboard( const_cast(&rWin) ); +} + +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) ) + { + sal_uInt16 aRotation = aMetadata.getRotation(); + if (aRotation != 0) + { + std::unique_ptr xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/queryrotateintostandarddialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("QueryRotateIntoStandardOrientationDialog")); + if (xQueryBox->run() == RET_YES) + { + GraphicNativeTransform aTransform( aGraphic ); + aTransform.rotate( aRotation ); + } + } + } + } +} + +sal_Bool SAL_CALL SwTransferable::isComplex() +{ + // Copy into a new Doc so we don't mess with the existing one. + //FIXME: We *should* be able to avoid this and improve the performance. + m_pClpDocFac.reset(new SwDocFac); + SwDoc* const pTmpDoc = lcl_GetDoc(*m_pClpDocFac); + + pTmpDoc->getIDocumentFieldsAccess() + .LockExpFields(); // never update fields - leave text as it is + lclOverWriteDoc(*m_pWrtShell, *pTmpDoc); + + sal_Int32 nTextLength = 0; + const SwNode* pEndOfContent = &m_pWrtShell->GetDoc()->GetNodes().GetEndOfContent(); + SwNodes& aNodes = pTmpDoc->GetNodes(); + for( sal_uLong nIndex = 0; nIndex < aNodes.Count(); ++nIndex) + { + SwNode& rNd = *aNodes[nIndex]; + if (&rNd == pEndOfContent) + break; + + if (rNd.IsOLENode() || rNd.IsGrfNode()) + return true; // Complex + + SwTextNode* pTextNode = rNd.GetTextNode(); + if (pTextNode) + { + 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::DbForm) & nSelectionType)) + { + m_pClpGraphic.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic )) + m_pOrigGraphic = m_pClpGraphic.get(); + m_pClpBitmap.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap )) + m_pOrigGraphic = m_pClpBitmap.get(); + + // is it a URL-Button ? + OUString sURL; + OUString sDesc; + if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) ) + { + m_pBookmark.reset(new INetBookmark( sURL, sDesc )); + m_eBufferType = TransferBufferType::InetField; + } + } + + m_pClpDocFac.reset(new SwDocFac); + SwDoc *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac); + + pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is + lclOverWriteDoc(*m_pWrtShell, *pTmpDoc); + + // in CORE a new one was created (OLE-objects copied!) + m_aDocShellRef = pTmpDoc->GetTmpDocShell(); + if( m_aDocShellRef.Is() ) + SwTransferable::InitOle( m_aDocShellRef ); + pTmpDoc->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_pBookmark.reset(new INetBookmark( + static_cast(aContentAtPos.aFnd.pAttr)->GetValue(), + aContentAtPos.sStr )); + m_eBufferType = TransferBufferType::InetField; + if( bSelect ) + m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT ); + } + } + if( m_pWrtShell->IsFrameSelected() ) + { + SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items{} ); + 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 *const pDoc = lcl_GetDoc(*m_pClpDocFac); + bOK = SetObject( pDoc->getIDocumentDrawModelAccess().GetDrawModel(), + SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor ); + } + break; + + case SotClipboardFormatId::STRING: + { + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor ); + } + break; + case SotClipboardFormatId::RTF: + { + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor ); + } + break; + case SotClipboardFormatId::RICHTEXT: + { + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + bOK = SetObject( pDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor ); + } + break; + + case SotClipboardFormatId::HTML: + { + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + bOK = SetObject( pDoc, 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_pClpGraphic->GetGDIMetaFile() ); + break; + case SotClipboardFormatId::BITMAP: + case SotClipboardFormatId::PNG: + // Neither pClpBitmap nor pClpGraphic are necessarily set + if( (m_eBufferType & TransferBufferType::Graphic) && (m_pClpBitmap != nullptr || m_pClpGraphic != nullptr)) + bOK = SetBitmapEx( (m_pClpBitmap ? m_pClpBitmap : m_pClpGraphic)->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_pBookmark ) + bOK = SetINetBookmark( *m_pBookmark, rFlavor ); + break; + + case SotClipboardFormatId::EMBED_SOURCE: + if( !m_aDocShellRef.Is() ) + { + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + SwDocShell* pNewDocSh = new SwDocShell( pDoc, + 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& 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(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 xDocOut( new utl::OOutputStreamWrapper( *xStream ) ); + if( SvxDrawingLayerExport( pModel, xDocOut ) ) + xStream->Commit(); + } + + bRet = ERRCODE_NONE == xStream->GetError(); + } + break; + + case SWTRANSFER_OBJECTTYPE_SWOLE: + { + SfxObjectShell* pEmbObj = static_cast(pObject); + try + { + ::utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference< embed::XStorage > xWorkStore = + ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), 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(); + + std::unique_ptr pSrcStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ )); + if( pSrcStm ) + { + xStream->SetBufferSize( 0xff00 ); + xStream->WriteStream( *pSrcStm ); + pSrcStm.reset(); + } + + xWorkStore->dispose(); + xWorkStore.clear(); + xStream->Commit(); + } + catch (const uno::Exception&) + { + } + + bRet = ( xStream->GetError() == ERRCODE_NONE ); + } + break; + + case SWTRANSFER_OBJECTTYPE_DDE: + { + xStream->SetBufferSize( 1024 ); + SwTransferDdeLink* pDdeLnk = static_cast(pObject); + if( pDdeLnk->WriteData( *xStream ) ) + { + xStream->Commit(); + bRet = ERRCODE_NONE == xStream->GetError(); + } + } + break; + + case SWTRANSFER_OBJECTTYPE_HTML: + { + // LOK is interested in getting images embedded for copy/paste support. + const OUString aFilterOptions("EmbedImages"); + GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? aFilterOptions : OUString(), OUString(), xWrt ); + break; + } + + case SWTRANSFER_OBJECTTYPE_RTF: + case SWTRANSFER_OBJECTTYPE_RICHTEXT: + GetRTFWriter(OUString(), OUString(), xWrt); + break; + + case SWTRANSFER_OBJECTTYPE_STRING: + GetASCWriter(OUString(), 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(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 + xStream->Commit(); + 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 ); +} + +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_pClpGraphic.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic )) + m_pOrigGraphic = m_pClpGraphic.get(); + m_pClpBitmap.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap )) + m_pOrigGraphic = m_pClpBitmap.get(); + + m_pClpDocFac.reset(new SwDocFac); + SwDoc *const pDoc = lcl_GetDoc(*m_pClpDocFac); + m_pWrtShell->Copy( pDoc ); + +#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 *const pDoc = lcl_GetDoc(*m_pClpDocFac); + m_aDocShellRef = new SwDocShell( pDoc, SfxObjectCreateMode::EMBEDDED); + m_aDocShellRef->DoInitNew(); + m_pWrtShell->Copy( pDoc ); + + AddFormat( SotClipboardFormatId::EMBED_SOURCE ); + + // --> OD #i98753# + // set size of embedded object at the object description structure + m_aObjDesc.maSize = OutputDevice::LogicToLogic(m_pWrtShell->GetObjSize(), MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM)); + // <-- + 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::unique_ptr pWait; + if( m_pWrtShell->ShouldWait() ) + pWait.reset(new SwWait( *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 *const pTmpDoc = lcl_GetDoc(*m_pClpDocFac); + + pTmpDoc->getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is + lclOverWriteDoc(*m_pWrtShell, *pTmpDoc); + + { + IDocumentMarkAccess* const pMarkAccess = pTmpDoc->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); + } + + // a new one was created in CORE (OLE objects copied!) + m_aDocShellRef = pTmpDoc->GetTmpDocShell(); + if( m_aDocShellRef.Is() ) + SwTransferable::InitOle( m_aDocShellRef ); + pTmpDoc->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::Graphic | m_eBufferType ); + + m_pClpGraphic.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic )) + m_pOrigGraphic = m_pClpGraphic.get(); + m_pClpBitmap.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap )) + m_pOrigGraphic = m_pClpBitmap.get(); + + // 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. + Size aSz( OLESIZE ); + m_aObjDesc.maSize = OutputDevice::LogicToLogic(aSz, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM)); + + PrepareOLE( m_aObjDesc ); +#if HAVE_FEATURE_DESKTOP + AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ); +#endif + } + else + nRet = 0; + + if( m_pWrtShell->IsFrameSelected() ) + { + SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items{} ); + 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 *const pDoc = lcl_GetDoc(*m_pClpDocFac); + m_pWrtShell->Copy(pDoc, & 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 *const pCDoc = lcl_GetDoc(*m_pClpDocFac); + + SwNodes& rNds = pCDoc->GetNodes(); + SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() ); + SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to 1st ContentNode + SwPaM aPam( *pCNd ); + + pCDoc->getIDocumentFieldsAccess().LockExpFields(); // never update fields - leave text as it is + + pCDoc->InsertGlossary( rGlossary, rStr, aPam ); + + // a new one was created in CORE (OLE-Objects copied!) + m_aDocShellRef = pCDoc->GetTmpDocShell(); + if( m_aDocShellRef.Is() ) + SwTransferable::InitOle( m_aDocShellRef ); + pCDoc->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. + Size aSz( OLESIZE ); + m_aObjDesc.maSize = OutputDevice::LogicToLogic(aSz, MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM)); + + 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 SwNodeIndex& rNodeIndex = pCursor->GetPoint()->nNode; + m_pPaM.reset(new SwPaM(rNodeIndex, rNodeIndex, 0, -1)); + m_nStartContent = pCursor->GetPoint()->nContent.GetIndex(); +} + +void SwPasteContext::forget() { m_pPaM.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 + <<= SwXTextGraphicObject::CreateXTextGraphicObject(*pFormat->GetDoc(), pFormat); + break; + } + + default: + { + if (!m_pPaM) + return; + + SwPaM* pCursor = m_rWrtShell.GetCursor(); + if (!pCursor) + return; + + if (!pCursor->GetPoint()->nNode.GetNode().IsTextNode()) + // Non-text was pasted. + return; + + // Update mark after paste. + *m_pPaM->GetMark() = *pCursor->GetPoint(); + + // Restore point. + ++m_pPaM->GetPoint()->nNode; + SwNode& rNode = m_pPaM->GetNode(); + if (!rNode.IsTextNode()) + // Starting point is no longer text. + return; + + m_pPaM->GetPoint()->nContent.Assign(static_cast(&rNode), + m_nStartContent); + + aPropertyValue.Name = "TextRange"; + const uno::Reference xTextRange = SwXTextRange::CreateXTextRange( + *m_pPaM->GetDoc(), *m_pPaM->GetPoint(), m_pPaM->GetMark()); + aPropertyValue.Value <<= xTextRange; + break; + } + } + + if (aPropertyValue.Name.isEmpty()) + return; + + // Invoke the listeners. + uno::Sequence aEvent{ aPropertyValue }; + + comphelper::OInterfaceIteratorHelper2 it(m_rWrtShell.GetPasteListeners()); + while (it.hasMoreElements()) + { + uno::Reference xListener(it.next(), UNO_QUERY); + if (xListener.is()) + xListener->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( 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; +} + +bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments, PasteTableType ePasteTable) +{ + SwPasteContext aPasteContext(rSh); + + sal_uInt8 nEventAction, 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( rData.GetXTransferable() ); + nAction = SotExchange::GetExchangeAction( + rData.GetDataFlavorExVector(), + nDestination, + nSourceOptions, /* ?? */ + EXCHG_IN_ACTION_DEFAULT, /* ?? */ + nFormat, nEventAction, SotClipboardFormatId::NONE, + lcl_getTransferPointer ( xTransferable ), + &nActionFlags ); + } + + // 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(aExpand.getToken(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 ) && + rSh.GetDoc()->IsIdxInTable(rSh.GetCursor()->GetNode()) != 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) + do + { + // 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 (rSh.GetDoc()->IsIdxInTable(rSh.GetCursor()->GetNode()) != nullptr); + if ( SwTransferable::PasteData( rData, rSh, EXCHG_OUT_ACTION_INSERT_STRING, nActionFlags, SotClipboardFormatId::HTML, + nDestination, false, false, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable) ) + { + pDispatch->Execute(FN_CHAR_LEFT, SfxCallMode::SYNCHRON); + 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); + 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 ) && + rSh.GetDoc()->IsIdxInTable(rSh.GetCursor()->GetNode()) != 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(" -1 ) + { + // table rows with span use also tbody + bool bShifted = aExpand.indexOf("") > -1; + // calculate count of selected rows or columns + sal_Int32 nSelectedRowsOrCols = 0; + const OUString sSearchRowOrCol = bRowMode ? OUString("") : OUString(" -1) + { + // skip rows/columns of nested tables, based on HTML indentation + if (nIdx > 2 && (aExpand[nIdx-1] != '\t' || aExpand[nIdx-2] != '\t' || (bShifted && aExpand[nIdx-3] != '\t'))) + ++nSelectedRowsOrCols; + ++nIdx; + } + // are we at the beginning of the cell? + bool bStartTableBoxNode = + // first paragraph of the cell? + rSh.GetCursor()->GetNode().GetIndex() == rSh.GetCursor()->GetNode().FindTableBoxStartNode()->GetIndex()+1 && + // beginning of the paragraph? + !rSh.GetCursor()->GetPoint()->nContent.GetIndex(); + 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 ) + { + SfxUInt16Item 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> pAction; + SwModule* pMod = SW_MOD(); + + bool bRet = false; + bool bCallAutoCaption = false; + + if( pPt ) + { + // external Drop + if( bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop ) + { + 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 ) ) + { + 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( TransferableDataHelper& rData, + SwWrtShell& rSh, SotClipboardFormatId nFormat, bool bMsg, bool bIgnoreComments ) +{ + const char* pResId = STR_CLPBRD_FORMAT_ERROR; + bool bRet = false; + + MSE40HTMLClipFormatObj aMSE40ClpObj; + + tools::SvRef 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(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 aOldLink( rSh.GetChgLnk() ); + rSh.SetChgLnk( Link() ); + + 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 = nullptr; + 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 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 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&) + { + } + } + } + } + + 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( 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.Insert(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.Insert(sURL, OUString(), aGraphic); + } + break; + default: + bRet = false; + } + } + } + else + bRet = true; + } + + if( bRet ) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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( TransferableDataHelper& rData, + SwWrtShell& rWrtShell, bool bReReadGrf, + bool bMsg ) +{ + // data from Clipboardformat + OUString aApp, aTopic, aItem; + + { + tools::SvRef xStrm; + if( !rData.GetSotStorageStream( SotClipboardFormatId::LINK, xStrm )) + { + OSL_ENSURE( false, "DDE Data not found." ); + return false; + } // report useful error!! + + rtl_TextEncoding eEncoding = DDE_TXT_ENCODING; + 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.Insert( 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(pTyp)->GetCmd(), aCmd ) && + SfxLinkUpdateMode::ALWAYS == static_cast(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(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 ) ) ) + { + const sal_Int32 nRows = nNewlines ? nNewlines-1 : 0; + const sal_Int32 nCols = comphelper::string::getTokenCount(aExpand.getToken(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 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 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.Insert( 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( TransferableDataHelper& rData, + SwWrtShell& rSh, SwPasteSdr nAction, + const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste) +{ + bool bRet = false; + tools::SvRef 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( 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 xStm; + + if(rData.GetSotStorageStream(SotClipboardFormatId::SVXB, xStm)) + { + ReadGraphic( *xStm, 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(), + 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 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(), aBuf.get(), + Link(), 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.Insert(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() ) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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.Insert(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, IMAP_FORMAT_DETECT ) == IMAP_ERR_OK && + aMap.GetIMapObjectCount() ) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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( TransferableDataHelper& rData, + SwWrtShell& rSh ) +{ + bool bRet = false; + if( rData.HasFormat( SotClipboardFormatId::SVIM )) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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( 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: + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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(), false ); + std::shared_ptr 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::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: + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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( 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( rSh.GetDrawView() ); + if (pFmView && pDragPt) + { + const OXFormsDescriptor &rDesc = OXFormsTransferable::extractDescriptor(rData); + SdrObjectUniquePtr pObj = pFmView->CreateXFormsControl(rDesc); + if(pObj) + { + rSh.SwFEShell::InsertDrawObj( *(pObj.release()), *pDragPt ); + } + } + } + else if( nWh ) + { + std::unique_ptr pConnectionItem; + std::unique_ptr pCursorItem; + std::unique_ptr pColumnItem; + std::unique_ptr pSourceItem; + std::unique_ptr pCommandItem; + std::unique_ptr pCommandTypeItem; + std::unique_ptr pColumnNameItem; + std::unique_ptr 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, makeAny(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( rSh.GetDrawView() ); + if (pFmView && bHaveColumnDescriptor && pDragPt) + { + SdrObjectUniquePtr pObj = pFmView->CreateFieldControl( OColumnTransferable::extractColumnDescriptor(rData) ); + if (pObj) + rSh.SwFEShell::InsertDrawObj( *(pObj.release()), *pDragPt ); + } + } + bRet = true; + } + else if( bMsg ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_CLPBRD_FORMAT_ERROR))); + xBox->run(); + } + return bRet; +} + +bool SwTransferable::PasteFileList( 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 ) + { + 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 xBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_CLPBRD_FORMAT_ERROR))); + xBox->run(); + } + return bRet; +} + +bool SwTransferable::CheckForURLOrLNKFile( 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(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( 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, nEventAction; + if( rData.HasFormat( nFormat )) { + uno::Reference xTransferable( rData.GetXTransferable() ); + 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& pDlg ) +{ + DataFlavorExVector aFormats( rData.GetDataFlavorExVector() ); + TransferableObjectDescriptor aDesc; + + SotExchangeDest nDest = SwTransferable::GetSotDestination( rSh ); + + SwTransferable *pClipboard = GetSwTransferable( rData ); + if( pClipboard ) + { + aDesc = pClipboard->m_aObjDesc; + const char* 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; + else + pResId = nullptr; + + if (pResId) + { + if (strcmp(STR_PRIVATEOLE, pResId) == 0 || strcmp(STR_PRIVATEGRAPHIC, pResId) == 0) + { + // 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 ) + { + const char* 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; + else + pResId = nullptr; + + if (pResId) + rToFill.AddClipbrdFormat(SotClipboardFormatId::EMBED_SOURCE, + SwResId(pResId)); + } + else + { + TransferableObjectDescriptor aDesc; + if (rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR)) + { + (void)const_cast(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; + + m_pClpGraphic.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_pClpGraphic )) + m_pOrigGraphic = m_pClpGraphic.get(); + m_pClpBitmap.reset(new Graphic); + if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_pClpBitmap )) + m_pOrigGraphic = m_pClpBitmap.get(); + + // 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 = OutputDevice::LogicToLogic( Size( OLESIZE ), + MapMode(MapUnit::MapTwip), MapMode(MapUnit::Map100thMM)); + 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() ) + { + SfxItemSet aSet( m_pWrtShell->GetAttrPool(), svl::Items{} ); + 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_pBookmark ) + aTmp = *m_pBookmark; + + // 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 ) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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); + + 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); + + // store cursor + ::sw::mark::IMark* pMark = rSh.SetBookmark( + vcl::KeyCode(), + OUString(), + IDocumentMarkAccess::MarkType::UNO_BOOKMARK ); + + 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); + + // restore cursor position + if (pMark != nullptr) + { + rSh.GotoMark( pMark ); + rSh.getIDocumentMarkAccess()->deleteMark( pMark ); + } + + // paste rows above/columns before + pDispatch->Execute(bTableCol ? FN_TABLE_PASTE_COL_BEFORE : FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON); + + if( rSrcSh.GetDoc() != rSh.GetDoc() ) + rSrcSh.EndUndo(); + + 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(); + } + 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.GetSwCursor()->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 pNew = new SwTransferable( rSh ); + + pNew->m_pCreatorView = _pCreatorView; + + pMod->m_pXSelection = pNew.get(); + pNew->CopyToSelection( rSh.GetWin() ); +} + +void SwTransferable::ClearSelection( 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::ClearSelection( rSh.GetWin() ); + } +} + +namespace +{ + class theSwTransferableUnoTunnelId : public rtl::Static< UnoTunnelIdInit, SwTransferable > {}; +} + +const Sequence< sal_Int8 >& SwTransferable::getUnoTunnelId() +{ + return theSwTransferableUnoTunnelId::get().getSeq(); +} + +sal_Int64 SwTransferable::getSomething( const Sequence< sal_Int8 >& rId ) +{ + sal_Int64 nRet; + if( isUnoTunnelId(rId) ) + { + nRet = sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) ); + } + else + nRet = TransferableHelper::getSomething(rId); + return nRet; +} + +SwTransferable* SwTransferable::GetSwTransferable( const TransferableDataHelper& rData ) +{ + return comphelper::getUnoTunnelImplementation(rData.GetTransferable()); +} + +SwTransferDdeLink::SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh ) + : rTrnsfr(rTrans) + , pDocShell(nullptr) + , nOldTimeOut(0) + , bDelBookmrk(false) + , bInDisconnect(false) +{ + // we only end up here with table- or text selection + if( SelectionType::TableCell & rSh.GetSelectionType() ) + { + SwFrameFormat* pFormat = rSh.GetTableFormat(); + if( pFormat ) + 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) + { + sName = pMark->GetName(); + bDelBookmrk = true; + if( !bIsModified ) + rSh.ResetModified(); + } + else + sName.clear(); + rSh.DoUndo( bUndo ); + } + + if( !sName.isEmpty() && + nullptr != ( pDocShell = rSh.GetDoc()->GetDocShell() ) ) + { + // then we create our "server" and connect to it + refObj = pDocShell->DdeCreateLinkSource( sName ); + if( refObj.is() ) + { + refObj->AddConnectAdvise( this ); + refObj->AddDataAdvise( this, + OUString(), + ADVISEMODE_NODATA | ADVISEMODE_ONLYONCE ); + nOldTimeOut = refObj->GetUpdateTimeout(); + refObj->SetUpdateTimeout( 0 ); + } + } +} + +SwTransferDdeLink::~SwTransferDdeLink() +{ + if( refObj.is() ) + Disconnect( true ); +} + +::sfx2::SvBaseLink::UpdateResult SwTransferDdeLink::DataChanged( const OUString& , + const uno::Any& ) +{ + // well, that's it with the link + if( !bInDisconnect ) + { + if( FindDocShell() && pDocShell->GetView() ) + rTrnsfr.RemoveDDELinkFormat( pDocShell->GetView()->GetEditWin() ); + Disconnect( false ); + } + return SUCCESS; +} + +bool SwTransferDdeLink::WriteData( SvStream& rStrm ) +{ + if( !refObj.is() || !FindDocShell() ) + return false; + + rtl_TextEncoding eEncoding = DDE_TXT_ENCODING; + const OString aAppNm(OUStringToOString( + Application::GetAppName(), eEncoding)); + const OString aTopic(OUStringToOString( + pDocShell->GetTitle(SFX_TITLE_FULLNAME), eEncoding)); + const OString aName(OUStringToOString(sName, eEncoding)); + + std::unique_ptr 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 = pDocShell->GetDoc()->getIDocumentMarkAccess(); + IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->findMark(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 = refObj.get(); + SwServerObject& rServerObject = dynamic_cast(*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); + + // recreate as Bookmark + ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark( + aPaM, + sMarkName, + IDocumentMarkAccess::MarkType::BOOKMARK, + ::sw::mark::InsertMode::New); + rServerObject.SetDdeBookmark(*pNewMark); + } + + bDelBookmrk = 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 = bInDisconnect; + bInDisconnect = true; + + // destroy the unused bookmark again (without Undo!)? + if( bDelBookmrk && refObj.is() && FindDocShell() ) + { + SwDoc* pDoc = pDocShell->GetDoc(); + ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); + + // #i58448# + Link aSavedOle2Link( pDoc->GetOle2Link() ); + pDoc->SetOle2Link( Link() ); + + bool bIsModified = pDoc->getIDocumentState().IsModified(); + + IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); + pMarkAccess->deleteMark(pMarkAccess->findMark(sName)); + + if( !bIsModified ) + pDoc->getIDocumentState().ResetModified(); + // #i58448# + pDoc->SetOle2Link( aSavedOle2Link ); + + bDelBookmrk = false; + } + + if( refObj.is() ) + { + refObj->SetUpdateTimeout( nOldTimeOut ); + refObj->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! + refObj->RemoveAllDataAdvise( this ); + refObj.clear(); + } + bInDisconnect = bOldDisconnect; +} + +bool SwTransferDdeLink::FindDocShell() +{ + SfxObjectShell* pTmpSh = SfxObjectShell::GetFirst( checkSfxObjectShell ); + while( pTmpSh ) + { + if( pTmpSh == pDocShell ) // that's what we want to have + { + if( pDocShell->GetDoc() ) + return true; + break; // the Doc is not there anymore, so leave! + } + pTmpSh = SfxObjectShell::GetNext( *pTmpSh, checkSfxObjectShell ); + } + + pDocShell = nullptr; + return false; +} + +void SwTransferDdeLink::Closed() +{ + if( !bInDisconnect && refObj.is() ) + { + refObj->RemoveAllDataAdvise( this ); + refObj->RemoveConnectAdvise( this ); + refObj.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 000000000..af5a3de41 --- /dev/null +++ b/sw/source/uibase/docvw/AnchorOverlayObject.cxx @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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( const basegfx::B2DPolygon& rTriangle, + const basegfx::B2DPolygon& rLine, + const basegfx::B2DPolygon& rLineTop, + AnchorState aAnchorState, + const basegfx::BColor& rColor, + double fDiscreteLineWidth, + bool bLineSolid ) + : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), + maTriangle(rTriangle), + maLine(rLine), + maLineTop(rLineTop), + 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); + + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( + aDotDashArray, + fDistance + fDashLen); + + const drawinglayer::primitive2d::Primitive2DReference aStrokedLine( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + getLine(), + aLineAttribute, + 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; +} + +ImplPrimitive2DIDBlock(AnchorPrimitive, PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE) + +/*static*/ std::unique_ptr AnchorOverlayObject::CreateAnchorOverlayObject( + SwView const & rDocView, + const SwRect& aAnchorRect, + long aPageBorder, + const Point& aLineStart, + const Point& aLineEnd, + const Color& aColorAnchor ) +{ + std::unique_ptr 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) + , maTriangle() + , maLine() + , maLineTop() + , 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() ) + { + 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 000000000..180d01757 --- /dev/null +++ b/sw/source/uibase/docvw/AnchorOverlayObject.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_DOCVW_ANCHOROVERLAYOBJECT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_ANCHOROVERLAYOBJECT_HXX + +#include + +#include + +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 CreateAnchorOverlayObject( SwView const & rDocView, + const SwRect& aAnchorRect, + 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 + +#endif + +/* 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 000000000..847905385 --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationMenuButton.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 "AnnotationMenuButton.hxx" + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace sw::annotation { + +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))); +} + +AnnotationMenuButton::AnnotationMenuButton(sw::annotation::SwAnnotationWin& rSidebarWin) + : MenuButton(&rSidebarWin) + , mrSidebarWin(rSidebarWin) +{ + AddEventListener(LINK(&mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener)); + + SetAccessibleName(SwResId(STR_ACCESS_ANNOTATION_BUTTON_NAME)); + SetAccessibleDescription(SwResId(STR_ACCESS_ANNOTATION_BUTTON_DESC)); + SetQuickHelpText(GetAccessibleDescription()); +} + +AnnotationMenuButton::~AnnotationMenuButton() +{ + disposeOnce(); +} + +void AnnotationMenuButton::dispose() +{ + RemoveEventListener(LINK(&mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener)); + MenuButton::dispose(); +} + +void AnnotationMenuButton::Select() +{ + OString sIdent = GetCurItemIdent(); + if (sIdent.isEmpty()) + return; + + // tdf#136682 ensure this is the currently active sidebar win so the command + // operates in an active sidebar context + bool bSwitchedFocus = mrSidebarWin.SetActiveSidebarWin(); + + if (sIdent == "reply") + mrSidebarWin.ExecuteCommand(FN_REPLY); + if (sIdent == "resolve" || sIdent == "unresolve") + mrSidebarWin.ExecuteCommand(FN_RESOLVE_NOTE); + else if (sIdent == "delete") + mrSidebarWin.ExecuteCommand(FN_DELETE_COMMENT); + else if (sIdent == "deleteby") + mrSidebarWin.ExecuteCommand(FN_DELETE_NOTE_AUTHOR); + else if (sIdent == "deleteall") + mrSidebarWin.ExecuteCommand(FN_DELETE_ALL_NOTES); + else if (sIdent == "formatall") + mrSidebarWin.ExecuteCommand(FN_FORMAT_ALL_NOTES); + + if (bSwitchedFocus) + mrSidebarWin.UnsetActiveSidebarWin(); + mrSidebarWin.GrabFocusToDocument(); +} + +void AnnotationMenuButton::MouseButtonDown( const MouseEvent& rMEvt ) +{ + PopupMenu* pButtonPopup(GetPopupMenu()); + if (mrSidebarWin.IsReadOnly()) + { + pButtonPopup->EnableItem(pButtonPopup->GetItemId("reply"), false); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("resolve"), false); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("unresolve"), false); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("delete"), false ); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("deleteby"), false ); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("deleteall"), false ); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("formatall"), false ); + } + else + { + pButtonPopup->EnableItem(pButtonPopup->GetItemId("resolve"), !mrSidebarWin.IsResolved()); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("unresolve"), mrSidebarWin.IsResolved()); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("delete"), !mrSidebarWin.IsProtected()); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("deleteby")); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("deleteall")); + pButtonPopup->EnableItem(pButtonPopup->GetItemId("formatall")); + } + + if (mrSidebarWin.IsProtected()) + { + pButtonPopup->EnableItem(pButtonPopup->GetItemId("reply"), false); + } + else + { + SvtUserOptions aUserOpt; + OUString sAuthor; + if ((sAuthor = aUserOpt.GetFullName()).isEmpty()) + { + if ((sAuthor = aUserOpt.GetID()).isEmpty()) + { + sAuthor = SwResId(STR_REDLINE_UNKNOWN_AUTHOR); + } + } + // do not allow to reply to ourself and no answer possible if this note is in a protected section + if (sAuthor == mrSidebarWin.GetAuthor()) + { + pButtonPopup->EnableItem(pButtonPopup->GetItemId("reply"), false); + } + else + { + pButtonPopup->EnableItem(pButtonPopup->GetItemId("reply")); + } + } + + MenuButton::MouseButtonDown(rMEvt); +} + +void AnnotationMenuButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + bool bHighContrast = rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode(); + + if (bHighContrast) + rRenderContext.SetFillColor(COL_BLACK); + else + rRenderContext.SetFillColor(mrSidebarWin.ColorDark()); + rRenderContext.SetLineColor(); + const tools::Rectangle aRect(tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel()))); + rRenderContext.DrawRect(aRect); + + if (bHighContrast) + { + //draw rect around button + rRenderContext.SetFillColor(COL_BLACK); + rRenderContext.SetLineColor(COL_WHITE); + } + else + { + //draw button + Gradient aGradient; + if (IsMouseOver()) + aGradient = Gradient(GradientStyle::Linear, + ColorFromAlphaColor(80, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark()), + ColorFromAlphaColor(15, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark())); + else + aGradient = Gradient(GradientStyle::Linear, + ColorFromAlphaColor(15, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark()), + ColorFromAlphaColor(80, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark())); + rRenderContext.DrawGradient(aRect, aGradient); + + //draw rect around button + rRenderContext.SetFillColor(); + rRenderContext.SetLineColor(ColorFromAlphaColor(90, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark())); + } + rRenderContext.DrawRect(aRect); + + tools::Rectangle aSymbolRect(aRect); + // 25% distance to the left and right button border + const long nBorderDistanceLeftAndRight = ((aSymbolRect.GetWidth() * 250) + 500) / 1000; + aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight ); + aSymbolRect.AdjustRight( -nBorderDistanceLeftAndRight ); + // 40% distance to the top button border + const long nBorderDistanceTop = ((aSymbolRect.GetHeight() * 400) + 500) / 1000; + aSymbolRect.AdjustTop(nBorderDistanceTop ); + // 15% distance to the bottom button border + const long nBorderDistanceBottom = ((aSymbolRect.GetHeight() * 150) + 500) / 1000; + aSymbolRect.AdjustBottom( -nBorderDistanceBottom ); + DecorationView aDecoView(&rRenderContext); + aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, (bHighContrast ? COL_WHITE : COL_BLACK)); +} + +void AnnotationMenuButton::KeyInput(const KeyEvent& rKeyEvt) +{ + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + if (rKeyCode.GetCode() == KEY_TAB) + { + mrSidebarWin.ActivatePostIt(); + mrSidebarWin.GrabFocus(); + } + else + { + MenuButton::KeyInput(rKeyEvt); + } +} + +} // end of namespace sw::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/AnnotationMenuButton.hxx b/sw/source/uibase/docvw/AnnotationMenuButton.hxx new file mode 100644 index 000000000..2e8ce9221 --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationMenuButton.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_DOCVW_ANNOTATIONMENUBUTTON_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_ANNOTATIONMENUBUTTON_HXX + +#include + +namespace sw::annotation { + class SwAnnotationWin; +} + +namespace sw::annotation { + +class AnnotationMenuButton : public MenuButton +{ + public: + AnnotationMenuButton( sw::annotation::SwAnnotationWin& rSidebarWin ); + virtual ~AnnotationMenuButton() override; + virtual void dispose() override; + + // override MenuButton methods + virtual void Select() override; + + // override vcl::Window methods + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void KeyInput( const KeyEvent& rKeyEvt ) override; + + private: + sw::annotation::SwAnnotationWin& mrSidebarWin; +}; + +} // end of namespace sw::annotation + +#endif + +/* 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 000000000..da900ec54 --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationWin.cxx @@ -0,0 +1,507 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include "AnnotationMenuButton.hxx" +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ShadowOverlayObject.hxx" +#include "AnchorOverlayObject.hxx" +#include "OverlayRanges.hxx" +#include "SidebarTxtControl.hxx" + +#include + +namespace sw::annotation { + +SwAnnotationWin::SwAnnotationWin( SwEditWin& rEditWin, + SwPostItMgr& aMgr, + SwSidebarItem& rSidebarItem, + SwFormatField* aField ) + : Window(&rEditWin) + , maBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/annotationmenu.ui", "") + , mrMgr(aMgr) + , mrView(rEditWin.GetView()) + , mnEventId(nullptr) + , mpSidebarTextControl(nullptr) + , mpVScrollbar(nullptr) + , mpMetadataAuthor(nullptr) + , mpMetadataDate(nullptr) + , mpMenuButton(nullptr) + , mColorAnchor() + , mColorDark() + , mColorLight() + , mChangeColor() + , meSidebarPosition(sw::sidebarwindows::SidebarPosition::NONE) + , mPosSize() + , mAnchorRect() + , 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(aField->GetField())) + , mpButtonPopup(nullptr) +{ + mpShadow = sidebarwindows::ShadowOverlayObject::CreateShadowOverlayObject( mrView ); + if ( mpShadow ) + { + mpShadow->setVisible(false); + } + + mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame), + mrSidebarItem.GetFormatField(), + *this ); + + 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() +{ + mpButtonPopup.clear(); + maBuilder.disposeBuilder(); + + if (IsDisposed()) + return; + + mrMgr.DisconnectSidebarWinFromFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame), + *this ); + + Disable(); + + if ( mpSidebarTextControl ) + { + if ( mpOutlinerView ) + { + mpOutlinerView->SetWindow( nullptr ); + } + } + mpSidebarTextControl.disposeAndClear(); + + mpOutlinerView.reset(); + mpOutliner.reset(); + + if (mpMetadataAuthor) + { + mpMetadataAuthor->RemoveEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + } + mpMetadataAuthor.disposeAndClear(); + + if (mpMetadataResolved) + { + mpMetadataResolved->RemoveEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + } + mpMetadataResolved.disposeAndClear(); + + if (mpMetadataDate) + { + mpMetadataDate->RemoveEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + } + mpMetadataDate.disposeAndClear(); + + if (mpVScrollbar) + { + mpVScrollbar->RemoveEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + } + mpVScrollbar.disposeAndClear(); + + RemoveEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + + mpAnchor.reset(); + mpShadow.reset(); + + mpTextRangeOverlay.reset(); + + mpMenuButton.disposeAndClear(); + + if (mnEventId) + Application::RemoveUserEvent( mnEventId ); + + vcl::Window::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(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() ); + mpOutliner->EnableUndo( false ); + if( mpField->GetTextObject() ) + mpOutliner->SetText( *mpField->GetTextObject() ); + else + { + mpOutliner->Clear(); + GetOutlinerView()->SetAttribs(DefaultItem()); + 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::SetResolved(bool resolved) +{ + bool oldState = IsResolved(); + static_cast(mpFormatField->GetField())->SetResolved(resolved); + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + mrSidebarItem.bShow = !IsResolved() || (pVOpt->IsResolvedPostIts()); + + mpTextRangeOverlay.reset(); + + if(IsResolved()) + mpMetadataResolved->Show(); + else + mpMetadataResolved->Hide(); + + if(IsResolved() != oldState) + mbResolvedStateUpdated = true; + UpdateData(); + Invalidate(); +} + +void SwAnnotationWin::ToggleResolved() +{ + SetResolved(!IsResolved()); +} + +void SwAnnotationWin::ToggleResolvedForThread() +{ + GetTopReplyNote()->ToggleResolved(); + mrMgr.UpdateResolvedStatus(GetTopReplyNote()); + mrMgr.LayoutPostIts(); +} + +bool SwAnnotationWin::IsResolved() const +{ + return static_cast(mpFormatField->GetField())->GetResolved(); +} + +bool SwAnnotationWin::IsThreadResolved() +{ + // Not const because GetTopReplyNote isn't. + return GetTopReplyNote()->IsResolved(); +} + +void SwAnnotationWin::UpdateData() +{ + if ( mpOutliner->IsModified() || mbResolvedStateUpdated ) + { + IDocumentUndoRedo & rUndoRedo( + mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); + std::unique_ptr 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() ); + aPosition.nContent = pTextField->GetStart(); + rUndoRedo.AppendUndo( + std::make_unique(aPosition, *pOldField, *mpField, nullptr, 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() +{ + if (mrView.GetWrtShellPtr()->GotoField(*mpFormatField)) + { + 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 (mnEventId) + { + Application::RemoveUserEvent( mnEventId ); + mnEventId = nullptr; + } + } + // we delete the field directly, the Mgr cleans up the PostIt by listening + GrabFocusToDocument(); + mrView.GetWrtShellPtr()->ClearMark(); + mrView.GetWrtShellPtr()->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(); +} + +// returns a non-zero postit parent id, if exists, otherwise 0 for root comments +sal_uInt32 SwAnnotationWin::CalcParent() +{ + SwTextField* pTextField = mpFormatField->GetTextField(); + SwPosition aPosition( pTextField->GetTextNode() ); + aPosition.nContent = pTextField->GetStart(); + SwTextAttr * const pTextAttr = + pTextField->GetTextNode().GetTextAttrForCharAt( + aPosition.nContent.GetIndex() - 1, + RES_TXTATR_ANNOTATION ); + const SwField* pField = pTextAttr ? pTextAttr->GetFormatField().GetField() : nullptr; + sal_uInt32 nParentId = 0; + if (pField && pField->Which() == SwFieldIds::Postit) + { + const SwPostItField* pPostItField = static_cast(pField); + nParentId = pPostItField->GetPostItId(); + } + return nParentId; +} + +// counts how many SwPostItField we have right after the current one +sal_uInt32 SwAnnotationWin::CountFollowing() +{ + sal_uInt32 aCount = 1; // we start with 1, so we have to subtract one at the end again + SwTextField* pTextField = mpFormatField->GetTextField(); + SwPosition aPosition( pTextField->GetTextNode() ); + aPosition.nContent = pTextField->GetStart(); + + SwTextAttr * pTextAttr = pTextField->GetTextNode().GetTextAttrForCharAt( + aPosition.nContent.GetIndex() + 1, + RES_TXTATR_ANNOTATION ); + SwField* pField = pTextAttr + ? const_cast(pTextAttr->GetFormatField().GetField()) + : nullptr; + while ( pField && ( pField->Which()== SwFieldIds::Postit ) ) + { + aCount++; + pTextAttr = pTextField->GetTextNode().GetTextAttrForCharAt( + aPosition.nContent.GetIndex() + aCount, + RES_TXTATR_ANNOTATION ); + pField = pTextAttr + ? const_cast(pTextAttr->GetFormatField().GetField()) + : nullptr; + } + return aCount - 1; +} + +VclPtr SwAnnotationWin::CreateMenuButton() +{ + mpButtonPopup = maBuilder.get_menu("menu"); + sal_uInt16 nByAuthorId = mpButtonPopup->GetItemId("deleteby"); + OUString aText = mpButtonPopup->GetItemText(nByAuthorId); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1,GetAuthor()); + aText = aRewriter.Apply(aText); + mpButtonPopup->SetItemText(nByAuthorId, aText); + VclPtrInstance pMenuButton( *this ); + pMenuButton->SetPopupMenu( mpButtonPopup ); + pMenuButton->Show(); + return pMenuButton; +} + +void SwAnnotationWin::InitAnswer(OutlinerParaObject const * pText) +{ + // 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); + 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 (!pText->GetTextObject().GetText(0).isEmpty()) + GetOutlinerView()->GetEditView().InsertText(pText->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); + GetOutlinerView()->SetAttribs(DefaultItem()); + // 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() ); + IDocumentUndoRedo & rUndoRedo( + mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); + std::unique_ptr 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() ); + aPosition.nContent = pTextField->GetStart(); + rUndoRedo.AppendUndo( + std::make_unique(aPosition, *pOldField, *mpField, nullptr, true)); + } + mpOutliner->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); + mpOutliner->ClearModifyFlag(); + mpOutliner->GetUndoManager().Clear(); +} + +void SwAnnotationWin::UpdateText(const OUString& aText) +{ + mpOutliner->Clear(); + GetOutlinerView()->InsertText(aText); + UpdateData(); +} + +SvxLanguageItem SwAnnotationWin::GetLanguage() const +{ + // set initial language for outliner + SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpField->GetLanguage() ); + sal_uInt16 nLangWhichId = 0; + 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: OSL_FAIL("GetLanguage: wrong script type"); + } + return SvxLanguageItem(mpField->GetLanguage(),nLangWhichId); +} + +bool SwAnnotationWin::IsProtected() 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(); +} + +} // 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 000000000..9c3539f2e --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationWin2.cxx @@ -0,0 +1,1624 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include "SidebarWinAcc.hxx" +#include +#include +#include +#include +#include "SidebarTxtControl.hxx" +#include "SidebarScrollBar.hxx" +#include "AnchorOverlayObject.hxx" +#include "ShadowOverlayObject.hxx" +#include "OverlayRanges.hxx" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace sw::sidebarwindows; + +namespace +{ + +/// Translate absolute <-> relative twips: LOK wants absolute coordinates as output and gives absolute coordinates as input. +void lcl_translateTwips(vcl::Window const & rParent, vcl::Window& rChild, MouseEvent* pMouseEvent) +{ + // Set map mode, so that callback payloads will contain absolute coordinates instead of relative ones. + Point aOffset(rChild.GetOutOffXPixel() - rParent.GetOutOffXPixel(), rChild.GetOutOffYPixel() - rParent.GetOutOffYPixel()); + if (!rChild.IsMapModeEnabled()) + { + MapMode aMapMode(rChild.GetMapMode()); + aMapMode.SetMapUnit(MapUnit::MapTwip); + aMapMode.SetScaleX(rParent.GetMapMode().GetScaleX()); + aMapMode.SetScaleY(rParent.GetMapMode().GetScaleY()); + rChild.SetMapMode(aMapMode); + rChild.EnableMapMode(); + } + aOffset = rChild.PixelToLogic(aOffset); + MapMode aMapMode(rChild.GetMapMode()); + aMapMode.SetOrigin(aOffset); + aMapMode.SetMapUnit(rParent.GetMapMode().GetMapUnit()); + rChild.SetMapMode(aMapMode); + rChild.EnableMapMode(false); + + if (pMouseEvent) + { + // Set event coordinates, so they contain relative coordinates instead of absolute ones. + Point aPos = pMouseEvent->GetPosPixel(); + aPos.Move(-aOffset.getX(), -aOffset.getY()); + MouseEvent aMouseEvent(aPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(), pMouseEvent->GetButtons(), pMouseEvent->GetModifier()); + *pMouseEvent = aMouseEvent; + } +} + +/// Decide which one from the children of rParent should get rMouseEvent. +vcl::Window* lcl_getHitWindow(sw::annotation::SwAnnotationWin& rParent, const MouseEvent& rMouseEvent) +{ + vcl::Window* pRet = nullptr; + + rParent.EditWin().Push(PushFlags::MAPMODE); + rParent.EditWin().EnableMapMode(); + for (sal_Int16 i = rParent.GetChildCount() - 1; i >= 0; --i) + { + vcl::Window* pChild = rParent.GetChild(i); + + Point aPosition(rParent.GetPosPixel()); + aPosition.Move(pChild->GetPosPixel().getX(), pChild->GetPosPixel().getY()); + Size aSize(rParent.GetSizePixel()); + tools::Rectangle aRectangleLogic(rParent.EditWin().PixelToLogic(aPosition), rParent.EditWin().PixelToLogic(aSize)); + if (aRectangleLogic.IsInside(rMouseEvent.GetPosPixel())) + { + pRet = pChild; + break; + } + } + rParent.EditWin().Pop(); + return pRet; +} + +} + +namespace sw::annotation { + +#define METABUTTON_WIDTH 16 +#define METABUTTON_HEIGHT 18 +#define METABUTTON_AREA_WIDTH 30 +#define POSTIT_META_FIELD_HEIGHT sal_Int32(15) +#define POSTIT_MINIMUMSIZE_WITHOUT_META 50 + + +void SwAnnotationWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + Window::Paint(rRenderContext, rRect); + + if (mpMetadataAuthor->IsVisible()) + { + //draw left over space + if (Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + rRenderContext.SetFillColor(COL_BLACK); + } + else + { + rRenderContext.SetFillColor(mColorDark); + } + + sal_uInt32 boxHeight = mpMetadataAuthor->GetSizePixel().Height() + mpMetadataDate->GetSizePixel().Height(); + boxHeight += IsThreadResolved() ? mpMetadataResolved->GetSizePixel().Height() : 0; + + rRenderContext.SetLineColor(); + tools::Rectangle aRectangle(Point(mpMetadataAuthor->GetPosPixel().X() + mpMetadataAuthor->GetSizePixel().Width(), + mpMetadataAuthor->GetPosPixel().Y()), + Size(GetMetaButtonAreaWidth(), boxHeight)); + + if (comphelper::LibreOfficeKit::isActive()) + aRectangle = rRect; + else + aRectangle = PixelToLogic(aRectangle); + rRenderContext.DrawRect(aRectangle); + } +} + +void SwAnnotationWin::PaintTile(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + Paint(rRenderContext, rRect); + + for (sal_uInt16 i = 0; i < GetChildCount(); ++i) + { + vcl::Window* pChild = GetChild(i); + + // No point in showing this button till click on it are not handled. + if (pChild == mpMenuButton.get()) + continue; + + if (!pChild->IsVisible()) + continue; + + rRenderContext.Push(PushFlags::MAPMODE); + Point aOffset(PixelToLogic(pChild->GetPosPixel())); + MapMode aMapMode(rRenderContext.GetMapMode()); + aMapMode.SetOrigin(aMapMode.GetOrigin() + aOffset); + rRenderContext.SetMapMode(aMapMode); + + bool bPopChild = false; + if (pChild->GetMapMode().GetMapUnit() != rRenderContext.GetMapMode().GetMapUnit()) + { + // This is needed for the scrollbar that has its map unit in pixels. + pChild->Push(PushFlags::MAPMODE); + bPopChild = true; + pChild->EnableMapMode(); + aMapMode = pChild->GetMapMode(); + aMapMode.SetMapUnit(rRenderContext.GetMapMode().GetMapUnit()); + aMapMode.SetScaleX(rRenderContext.GetMapMode().GetScaleX()); + aMapMode.SetScaleY(rRenderContext.GetMapMode().GetScaleY()); + pChild->SetMapMode(aMapMode); + } + + pChild->Paint(rRenderContext, rRect); + + if (bPopChild) + pChild->Pop(); + rRenderContext.Pop(); + } + + const drawinglayer::geometry::ViewInformation2D aViewInformation; + std::unique_ptr pProcessor(drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(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(PushFlags::NONE); + pProcessor.reset(); + rRenderContext.Push(PushFlags::NONE); +} + +bool SwAnnotationWin::IsHitWindow(const Point& rPointLogic) +{ + tools::Rectangle aRectangleLogic(EditWin().PixelToLogic(GetPosPixel()), EditWin().PixelToLogic(GetSizePixel())); + return aRectangleLogic.IsInside(rPointLogic); +} + +void SwAnnotationWin::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark) +{ + mpSidebarTextControl->Push(PushFlags::MAPMODE); + MouseEvent aMouseEvent(rPosition); + lcl_translateTwips(EditWin(), *mpSidebarTextControl, &aMouseEvent); + Point aPosition(aMouseEvent.GetPosPixel()); + + EditView& rEditView = GetOutlinerView()->GetEditView(); + rEditView.SetCursorLogicPosition(aPosition, bPoint, bClearMark); + + mpSidebarTextControl->Pop(); +} + +void SwAnnotationWin::Draw(OutputDevice* pDev, const Point& rPt, DrawFlags nInFlags) +{ + Size aSz = pDev->PixelToLogic(GetSizePixel()); + + if (mpMetadataAuthor->IsVisible() ) + { + pDev->SetFillColor(mColorDark); + pDev->SetLineColor(); + pDev->DrawRect( tools::Rectangle( rPt, aSz ) ); + } + + if (mpMetadataAuthor->IsVisible()) + { + vcl::Font aOrigFont(mpMetadataAuthor->GetControlFont()); + Point aPos(PixelToLogic(mpMetadataAuthor->GetPosPixel())); + aPos += rPt; + vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataAuthor->SetControlFont( aFont ); + mpMetadataAuthor->Draw(pDev, aPos, nInFlags); + mpMetadataAuthor->SetControlFont( aOrigFont ); + } + + if (mpMetadataDate->IsVisible()) + { + vcl::Font aOrigFont(mpMetadataDate->GetControlFont()); + Point aPos(PixelToLogic(mpMetadataDate->GetPosPixel())); + aPos += rPt; + vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataDate->SetControlFont( aFont ); + mpMetadataDate->SetControlFont( aOrigFont ); + } + + if (mpMetadataResolved->IsVisible()) + { + vcl::Font aOrigFont(mpMetadataResolved->GetControlFont()); + Point aPos(PixelToLogic(mpMetadataResolved->GetPosPixel())); + aPos += rPt; + vcl::Font aFont( mpMetadataResolved->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataResolved->SetControlFont( aFont ); + mpMetadataResolved->SetControlFont( aOrigFont ); + } + + Size aOrigSize(mpSidebarTextControl->GetSizePixel()); + mpSidebarTextControl->SetSizePixel(aSz); + mpSidebarTextControl->Draw(pDev, rPt, nInFlags); + mpSidebarTextControl->SetSizePixel(aOrigSize); + + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + std::unique_ptr pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( + *pDev, aNewViewInfos )); + + if (mpAnchor) + pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence()); + if (mpTextRangeOverlay) + pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence()); + pProcessor.reset(); + + if (!mpVScrollbar->IsVisible()) + return; + + vcl::Font aOrigFont(mpMetadataDate->GetControlFont()); + Color aOrigBg( mpMetadataDate->GetControlBackground() ); + OUString sOrigText(mpMetadataDate->GetText()); + + Point aPos(PixelToLogic(mpMenuButton->GetPosPixel())); + aPos += rPt; + + vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataDate->SetControlFont( aFont ); + mpMetadataDate->SetControlBackground( Color(0xFFFFFF) ); + mpMetadataDate->SetText("..."); + aOrigSize = mpMetadataDate->GetSizePixel(); + mpMetadataDate->SetSizePixel(mpMenuButton->GetSizePixel()); + mpMetadataDate->Draw(pDev, aPos, nInFlags); + mpMetadataDate->SetSizePixel(aOrigSize); + + mpMetadataDate->SetText(sOrigText); + mpMetadataDate->SetControlFont( aOrigFont ); + mpMetadataDate->SetControlBackground( aOrigBg ); +} + +void SwAnnotationWin::KeyInput(const KeyEvent& rKeyEvent) +{ + if (mpSidebarTextControl) + { + mpSidebarTextControl->Push(PushFlags::MAPMODE); + lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr); + + mpSidebarTextControl->KeyInput(rKeyEvent); + + mpSidebarTextControl->Pop(); + } +} + +void SwAnnotationWin::MouseMove(const MouseEvent& rMouseEvent) +{ + if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent)) + { + pHit->Push(PushFlags::MAPMODE); + MouseEvent aMouseEvent(rMouseEvent); + lcl_translateTwips(EditWin(), *pHit, &aMouseEvent); + + pHit->MouseMove(aMouseEvent); + + pHit->Pop(); + } +} + +void SwAnnotationWin::MouseButtonDown(const MouseEvent& rMouseEvent) +{ + if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent)) + { + pHit->Push(PushFlags::MAPMODE); + MouseEvent aMouseEvent(rMouseEvent); + lcl_translateTwips(EditWin(), *pHit, &aMouseEvent); + + pHit->MouseButtonDown(aMouseEvent); + + pHit->Pop(); + } +} + +void SwAnnotationWin::MouseButtonUp(const MouseEvent& rMouseEvent) +{ + if (vcl::Window* pHit = lcl_getHitWindow(*this, rMouseEvent)) + { + pHit->Push(PushFlags::MAPMODE); + MouseEvent aMouseEvent(rMouseEvent); + lcl_translateTwips(EditWin(), *pHit, &aMouseEvent); + + pHit->MouseButtonUp(aMouseEvent); + + pHit->Pop(); + } +} + +void SwAnnotationWin::SetPosSizePixelRect(long nX, long nY, long nWidth, long nHeight, + const SwRect& aAnchorRect, const long aPageBorder) +{ + mPosSize = tools::Rectangle(Point(nX,nY),Size(nWidth,nHeight)); + if (!mAnchorRect.IsEmpty() && mAnchorRect != aAnchorRect) + mbAnchorRectChanged = true; + mAnchorRect = aAnchorRect; + mPageBorder = aPageBorder; +} + +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 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); +} + +SfxItemSet SwAnnotationWin::DefaultItem() +{ + SfxItemSet aItem( mrView.GetDocShell()->GetPool() ); + aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT)); + return aItem; +} + +void SwAnnotationWin::InitControls() +{ + AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + + // actual window which holds the user text + mpSidebarTextControl = VclPtr::Create( *this, + WB_NODIALOGCONTROL, + mrView, mrMgr ); + mpSidebarTextControl->SetPointer(PointerStyle::Text); + + // window controls for author and date + mpMetadataAuthor = VclPtr::Create( this, 0 ); + mpMetadataAuthor->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) ); + mpMetadataAuthor->EnableRTL(AllSettings::GetLayoutRTL()); + mpMetadataAuthor->SetReadOnly(); + mpMetadataAuthor->AlwaysDisableInput(true); + mpMetadataAuthor->SetCallHandlersOnInputDisabled(true); + mpMetadataAuthor->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + { + AllSettings aSettings = mpMetadataAuthor->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + vcl::Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetFontHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataAuthor->SetSettings(aSettings); + } + + mpMetadataDate = VclPtr::Create( this, 0 ); + mpMetadataDate->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_DATE_NAME ) ); + mpMetadataDate->EnableRTL(AllSettings::GetLayoutRTL()); + mpMetadataDate->SetReadOnly(); + mpMetadataDate->AlwaysDisableInput(true); + mpMetadataDate->SetCallHandlersOnInputDisabled(true); + mpMetadataDate->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + { + AllSettings aSettings = mpMetadataDate->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + vcl::Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetFontHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataDate->SetSettings(aSettings); + } + + mpMetadataResolved = VclPtr::Create( this, 0 ); + mpMetadataResolved->SetAccessibleName( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) ); + mpMetadataResolved->EnableRTL(AllSettings::GetLayoutRTL()); + mpMetadataResolved->SetReadOnly(); + mpMetadataResolved->AlwaysDisableInput(true); + mpMetadataResolved->SetCallHandlersOnInputDisabled(true); + mpMetadataResolved->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + { + AllSettings aSettings = mpMetadataResolved->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + vcl::Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetFontHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataResolved->SetSettings(aSettings); + mpMetadataResolved->SetText( SwResId( STR_ACCESS_ANNOTATION_RESOLVED_NAME ) ); + } + + SwDocShell* aShell = mrView.GetDocShell(); + mpOutliner.reset(new Outliner(&aShell->GetPool(),OutlinerMode::TextObject)); + aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner.get() ); + mpOutliner->SetUpdateMode( true ); + Rescale(); + + mpSidebarTextControl->EnableRTL( false ); + mpOutlinerView.reset(new OutlinerView ( mpOutliner.get(), mpSidebarTextControl )); + mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT); + mpOutliner->InsertView(mpOutlinerView.get() ); + mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,1,1) ) ); + + mpOutlinerView->SetAttribs(DefaultItem()); + + if (comphelper::LibreOfficeKit::isActive()) + { + // If there is a callback already registered, inform the new outliner view about it. + mpOutlinerView->RegisterViewShell(&mrView); + } + + //create Scrollbars + mpVScrollbar = VclPtr::Create(*this, WB_3DLOOK |WB_VSCROLL|WB_DRAG, mrView); + mpVScrollbar->EnableNativeWidget(false); + mpVScrollbar->EnableRTL( false ); + mpVScrollbar->SetScrollHdl(LINK(this, SwAnnotationWin, ScrollHdl)); + mpVScrollbar->EnableDrag(); + mpVScrollbar->AddEventListener( LINK( this, SwAnnotationWin, WindowEventListener ) ); + + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + EEControlBits nCntrl = mpOutliner->GetControlWord(); + // TODO: crash when AUTOCOMPLETE enabled + nCntrl |= EEControlBits::MARKFIELDS | EEControlBits::PASTESPECIAL | EEControlBits::AUTOCORRECT | EEControlBits::USECHARATTRIBS; // | EEControlBits::AUTOCOMPLETE; + if (SwViewOption::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(); + + mpMenuButton = CreateMenuButton(); + + SetLanguage(GetLanguage()); + GetOutlinerView()->StartSpeller(); + SetPostItText(); + mpOutliner->CompleteOnlineSpelling(); + + mpSidebarTextControl->Show(); + mpMetadataAuthor->Show(); + mpMetadataDate->Show(); + if(IsThreadResolved()) { mpMetadataResolved->Show(); } + mpVScrollbar->Show(); +} + +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 = sMeta.copy(0, 20) + "..."; + } + if ( mpMetadataAuthor->GetText() != sMeta ) + { + mpMetadataAuthor->SetText(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 ( mpMetadataDate->GetText() != sMeta ) + { + mpMetadataDate->SetText(sMeta); + } +} + +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() ); + mpOutliner->SetRefMapMode( aMode ); + SetMapMode( aMode ); + mpSidebarTextControl->SetMapMode( aMode ); + const Fraction& rFraction = mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY(); + if ( mpMetadataAuthor ) + { + vcl::Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction); + aFont.SetFontHeight( nHeight ); + mpMetadataAuthor->SetControlFont( aFont ); + } + if ( mpMetadataDate ) + { + vcl::Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction); + aFont.SetFontHeight( nHeight ); + mpMetadataDate->SetControlFont( aFont ); + } + if ( mpMetadataResolved ) + { + vcl::Font aFont( mpMetadataResolved->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = long(aFont.GetFontHeight() * rFraction); + aFont.SetFontHeight( nHeight ); + mpMetadataResolved->SetControlFont( aFont ); + } +} + +void SwAnnotationWin::SetPosAndSize() +{ + bool bChange = false; + + if (GetSizePixel() != mPosSize.GetSize()) + { + bChange = true; + SetSizePixel(mPosSize.GetSize()); + + if (comphelper::LibreOfficeKit::isActive()) + { + // Position is not yet set at VCL level, but the map mode should + // contain the right origin to emit the correct cursor position. + mpSidebarTextControl->Push(PushFlags::MAPMODE); + Point aOffset(mPosSize.Left(), mPosSize.Top()); + aOffset = PixelToLogic(aOffset); + MapMode aMapMode(mpSidebarTextControl->GetMapMode()); + aMapMode.SetOrigin(aOffset); + mpSidebarTextControl->SetMapMode(aMapMode); + mpSidebarTextControl->EnableMapMode(false); + } + + DoResize(); + + if (comphelper::LibreOfficeKit::isActive()) + mpSidebarTextControl->Pop(); + } + + if (GetPosPixel().X() != mPosSize.TopLeft().X() || (std::abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 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( " - 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 (mrMgr.ShowNotes()) + { + 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 != 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()->nNode = *pTextNode; + pTableCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 ); + pTableCursor->NewTableSelection(); + pTmpCursor = pTableCursor; + } + else + { + SwShellCursor* pCursor = new SwShellCursor( mrView.GetWrtShell(), aStartPos ); + pCursor->SetMark(); + pCursor->GetMark()->nNode = *pTextNode; + pCursor->GetMark()->nContent.Assign( pTextNode, pTextAnnotationField->GetStart()+1 ); + pTmpCursor = pCursor; + } + std::unique_ptr 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 (mrMgr.ShowNotes() && !maAnnotationTextRanges.empty()) + { + if ( mpTextRangeOverlay != nullptr ) + { + mpTextRangeOverlay->setRanges( 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, + maAnnotationTextRanges, + mpAnchor && mpAnchor->getLineSolid() ); + } + } + else + { + mpTextRangeOverlay.reset(); + } +} + +void SwAnnotationWin::DoResize() +{ + long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height(); + long aHeight = GetSizePixel().Height(); + unsigned long aWidth = GetSizePixel().Width(); + + aHeight -= GetMetaHeight(); + mpMetadataAuthor->Show(); + if(IsThreadResolved()) { mpMetadataResolved->Show(); } + mpMetadataDate->Show(); + mpSidebarTextControl->SetQuickHelpText(OUString()); + unsigned int numFields = GetNumFields(); + if (aTextHeight > aHeight) + { // we need vertical scrollbars and have to reduce the width + aWidth -= GetScrollbarWidth(); + mpVScrollbar->Show(); + } + else + { + mpVScrollbar->Hide(); + } + + { + const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(), + GetMetaHeight()/numFields ); + mpMetadataAuthor->setPosSizePixel( 0, + aHeight, + aSizeOfMetadataControls.Width(), + aSizeOfMetadataControls.Height() ); + mpMetadataDate->setPosSizePixel( 0, + aHeight + aSizeOfMetadataControls.Height(), + aSizeOfMetadataControls.Width(), + aSizeOfMetadataControls.Height() ); + if(IsThreadResolved()) { + mpMetadataResolved->setPosSizePixel( 0, + aHeight + aSizeOfMetadataControls.Height()*2, + aSizeOfMetadataControls.Width(), + aSizeOfMetadataControls.Height() ); + } + } + + mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ; + if (!mpVScrollbar->IsVisible()) + { // if we do not have a scrollbar anymore, we want to see the complete text + mpOutlinerView->SetVisArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) ); + } + mpOutlinerView->SetOutputArea( PixelToLogic( tools::Rectangle(0,0,aWidth,aHeight) ) ); + + if (!AllSettings::GetLayoutRTL()) + { + mpSidebarTextControl->setPosSizePixel(0, 0, aWidth, aHeight); + mpVScrollbar->setPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight); + } + else + { + mpSidebarTextControl->setPosSizePixel( ( aTextHeight > aHeight ? GetScrollbarWidth() : 0 ), 0, + aWidth, aHeight); + mpVScrollbar->setPosSizePixel( 0, 0, GetScrollbarWidth(), aHeight); + } + + mpVScrollbar->SetVisibleSize( PixelToLogic(Size(0,aHeight)).Height() ); + mpVScrollbar->SetPageSize( PixelToLogic(Size(0,aHeight)).Height() * 8 / 10 ); + mpVScrollbar->SetLineSize( mpOutliner->GetTextHeight() / 10 ); + SetScrollbar(); + mpVScrollbar->SetRange( Range(0, mpOutliner->GetTextHeight())); + + //calculate rects for meta- button + const Fraction& fx( GetMapMode().GetScaleX() ); + const Fraction& fy( GetMapMode().GetScaleY() ); + + const Point aPos( mpMetadataAuthor->GetPosPixel()); + mpMenuButton->setPosSizePixel( long(aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx), + long(aPos.Y()+5*fy), + long(METABUTTON_WIDTH*fx), + long(METABUTTON_HEIGHT*fy) ); +} + +void SwAnnotationWin::SetSizePixel( const Size& rNewSize ) +{ + Window::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() +{ + mpVScrollbar->SetThumbPos(mpOutlinerView->GetVisArea().Top()); +} + +void SwAnnotationWin::ResizeIfNecessary(long aOldHeight, long aNewHeight) +{ + if (aOldHeight != aNewHeight) + { + //check for lower border or next note + long aBorder = mrMgr.GetNextBorder(); + if (aBorder != -1) + { + if (aNewHeight > GetMinimumSizeWithoutMeta()) + { + 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() ) + { + { + mpMetadataAuthor->SetControlBackground(mColorDark); + AllSettings aSettings = mpMetadataAuthor->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnchor); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataAuthor->SetSettings(aSettings); + } + + { + mpMetadataDate->SetControlBackground(mColorDark); + AllSettings aSettings = mpMetadataDate->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnchor); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataDate->SetSettings(aSettings); + } + + { + mpMetadataResolved->SetControlBackground(mColorDark); + AllSettings aSettings = mpMetadataResolved->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnchor); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataResolved->SetSettings(aSettings); + } + + AllSettings aSettings2 = mpVScrollbar->GetSettings(); + StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings(); + aStyleSettings2.SetButtonTextColor(Color(0,0,0)); + aStyleSettings2.SetCheckedColor(mColorLight); // background + aStyleSettings2.SetShadowColor(mColorAnchor); + aStyleSettings2.SetFaceColor(mColorDark); + aSettings2.SetStyleSettings(aStyleSettings2); + mpVScrollbar->SetSettings(aSettings2); + } +} + +void SwAnnotationWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition) +{ + meSidebarPosition = eSidebarPosition; +} + +void SwAnnotationWin::SetReadonly(bool bSet) +{ + mbReadonly = bSet; + GetOutlinerView()->SetReadOnly(bSet); +} + +void SwAnnotationWin::SetLanguage(const SvxLanguageItem& rNewItem) +{ + IDocumentUndoRedo& rUndoRedo( + mrView.GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); + const bool bDocUndoEnabled = rUndoRedo.DoesUndo(); + const bool bOutlinerUndoEnabled = mpOutliner->IsUndoEnabled(); + const bool bOutlinerModified = mpOutliner->IsModified(); + const bool bDisableAndRestoreUndoMode = !bDocUndoEnabled && bOutlinerUndoEnabled; + + if (bDisableAndRestoreUndoMode) + { + // doc undo is disabled, but outliner was enabled, turn outliner undo off + // for the duration of this function + mpOutliner->EnableUndo(false); + } + + Link aLink = mpOutliner->GetModifyHdl(); + mpOutliner->SetModifyHdl( Link() ); + ESelection aOld = GetOutlinerView()->GetSelection(); + + ESelection aNewSelection( 0, 0, mpOutliner->GetParagraphCount()-1, EE_TEXTPOS_ALL ); + GetOutlinerView()->SetSelection( aNewSelection ); + SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs()); + aEditAttr.Put(rNewItem); + GetOutlinerView()->SetAttribs( aEditAttr ); + + if (!mpOutliner->IsUndoEnabled() && !bOutlinerModified) + { + // if undo was disabled (e.g. this is a redo action) and we were + // originally 'unmodified' keep it that way + mpOutliner->ClearModifyFlag(); + } + + GetOutlinerView()->SetSelection(aOld); + mpOutliner->SetModifyHdl( aLink ); + + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + EEControlBits nCntrl = mpOutliner->GetControlWord(); + // turn off + nCntrl &= ~EEControlBits::ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + //turn back on + if (pVOpt->IsOnlineSpell()) + nCntrl |= EEControlBits::ONLINESPELLING; + else + nCntrl &= ~EEControlBits::ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + mpOutliner->CompleteOnlineSpelling(); + + // restore original mode + if (bDisableAndRestoreUndoMode) + mpOutliner->EnableUndo(true); + + Invalidate(); +} + +void SwAnnotationWin::GetFocus() +{ + if (mpSidebarTextControl) + mpSidebarTextControl->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); + + // Invalidate. + InvalidateControl(); +} + +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); +} + +void SwAnnotationWin::InvalidateControl() +{ + // Invalidate. + mpSidebarTextControl->Push(PushFlags::MAPMODE); + lcl_translateTwips(EditWin(), *mpSidebarTextControl, nullptr); + mpSidebarTextControl->Invalidate(); + mpSidebarTextControl->Pop(); +} + +void SwAnnotationWin::ActivatePostIt() +{ + mrMgr.AssureStdModeAtShell(); + + mpOutliner->ClearModifyFlag(); + mpOutliner->GetUndoManager().Clear(); + + CheckMetaText(); + SetViewState(ViewState::EDIT); + GetOutlinerView()->ShowCursor(); + + mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->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 ( !IsProtected() && mpOutliner->GetEditEngine().GetText().isEmpty() ) + { + mnEventId = 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* pPara = new OutlinerParaObject(*GetOutlinerView()->GetEditView().CreateTextObject()); + mrMgr.RegisterAnswer(pPara); + } + if (mrMgr.HasActiveSidebarWin()) + mrMgr.SetActiveSidebarWin(nullptr); + SwitchToFieldPos(); + mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT); + break; + } + case FN_DELETE_COMMENT: + //Delete(); // do not kill the parent of our open popup menu + mnEventId = Application::PostUserEvent( LINK( this, SwAnnotationWin, DeleteHdl), nullptr, true ); + break; + case FN_RESOLVE_NOTE: + GetTopReplyNote()->ToggleResolved(); + 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(); +} + +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, WindowEventListener, VclWindowEvent&, rEvent, void ) +{ + if ( rEvent.GetId() == VclEventId::WindowMouseMove ) + { + MouseEvent* pMouseEvt = static_cast(rEvent.GetData()); + if ( pMouseEvt->IsEnterWindow() ) + { + mbMouseOver = true; + if ( !HasFocus() ) + { + SetViewState(ViewState::VIEW); + Invalidate(); + } + } + else if ( pMouseEvt->IsLeaveWindow()) + { + mbMouseOver = false; + if ( !HasFocus() ) + { + SetViewState(ViewState::NORMAL); + Invalidate(); + } + } + } + else if ( rEvent.GetId() == VclEventId::WindowActivate && + rEvent.GetWindow() == mpSidebarTextControl ) + { + SetActiveSidebarWin(); + mrMgr.MakeVisible( this ); + } +} + +bool SwAnnotationWin::SetActiveSidebarWin() +{ + if (mrMgr.GetActiveSidebarWin() == this) + return false; + const bool bLockView = mrView.GetWrtShell().IsViewLocked(); + mrView.GetWrtShell().LockView( true ); + mrMgr.SetActiveSidebarWin(this); + mrView.GetWrtShell().LockView( bLockView ); + return true; +} + +void SwAnnotationWin::UnsetActiveSidebarWin() +{ + if (mrMgr.GetActiveSidebarWin() != this) + return; + const bool bLockView = mrView.GetWrtShell().IsViewLocked(); + mrView.GetWrtShell().LockView( true ); + mrMgr.SetActiveSidebarWin(nullptr); + mrView.GetWrtShell().LockView( bLockView ); +} + +IMPL_LINK(SwAnnotationWin, ScrollHdl, ScrollBar*, pScroll, void) +{ + long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos(); + GetOutlinerView()->Scroll( 0, nDiff ); +} + +IMPL_LINK_NOARG(SwAnnotationWin, ModifyHdl, LinkParamNone*, void) +{ + mrView.GetDocShell()->SetModified(); +} + +IMPL_LINK_NOARG(SwAnnotationWin, DeleteHdl, void*, void) +{ + mnEventId = nullptr; + Delete(); +} + +void SwAnnotationWin::ResetAttributes() +{ + mpOutlinerView->RemoveAttribsKeepLanguages(true); + mpOutliner->RemoveFields(); + mpOutlinerView->SetAttribs(DefaultItem()); +} + +sal_Int32 SwAnnotationWin::GetScrollbarWidth() const +{ + return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10; +} + +sal_Int32 SwAnnotationWin::GetMetaButtonAreaWidth() const +{ + const Fraction& f( GetMapMode().GetScaleX() ); + return long(METABUTTON_AREA_WIDTH * f); +} + +sal_Int32 SwAnnotationWin::GetMetaHeight() +{ + const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY()); + const int fields = GetNumFields(); + return long(fields*POSTIT_META_FIELD_HEIGHT*f); +} + +sal_Int32 SwAnnotationWin::GetNumFields() +{ + return IsThreadResolved() ? 3 : 2; +} + +sal_Int32 SwAnnotationWin::GetMinimumSizeWithMeta() const +{ + return mrMgr.GetMinimumSizeWithMeta(); +} + +sal_Int32 SwAnnotationWin::GetMinimumSizeWithoutMeta() const +{ + const Fraction& f(mrView.GetWrtShellPtr()->GetOut()->GetMapMode().GetScaleY()); + return long(POSTIT_MINIMUMSIZE_WITHOUT_META * f); +} + +void SwAnnotationWin::SetSpellChecking() +{ + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + EEControlBits nCntrl = mpOutliner->GetControlWord(); + if (pVOpt->IsOnlineSpell()) + nCntrl |= EEControlBits::ONLINESPELLING; + else + nCntrl &= ~EEControlBits::ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + 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() +{ + SwAnnotationWin* pTopNote = this; + SwAnnotationWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : nullptr; + while (pSidebarWin) + { + pTopNote = pSidebarWin; + pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : nullptr; + } + return pTopNote; +} + +void SwAnnotationWin::SwitchToFieldPos() +{ + if ( mrMgr.GetActiveSidebarWin() == this ) + mrMgr.SetActiveSidebarWin(nullptr); + GotoPos(); + sal_uInt32 aCount = MoveCaret(); + if (aCount) + mrView.GetDocShell()->GetWrtShell()->SwCursorShell::Right(aCount, 0); + GrabFocusToDocument(); +} + +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 mpVScrollbar != nullptr; +} + +bool SwAnnotationWin::IsScrollbarVisible() const +{ + return HasScrollbar() && mpVScrollbar->IsVisible(); +} + +void SwAnnotationWin::ChangeSidebarItem( SwSidebarItem const & rSidebarItem ) +{ + const bool bAnchorChanged = mpAnchorFrame != rSidebarItem.maLayoutInfo.mpAnchorFrame; + if ( bAnchorChanged ) + { + mrMgr.DisconnectSidebarWinFromFrame( *mpAnchorFrame, *this ); + } + + mrSidebarItem = rSidebarItem; + mpAnchorFrame = mrSidebarItem.maLayoutInfo.mpAnchorFrame; + + if ( GetWindowPeer() ) + { + SidebarWinAccessible* pAcc = + static_cast( GetWindowPeer() ); + OSL_ENSURE( dynamic_cast( GetWindowPeer() ), + " - unexpected type of window peer -> crash possible!" ); + pAcc->ChangeSidebarItem( mrSidebarItem ); + } + + if ( bAnchorChanged ) + { + mrMgr.ConnectSidebarWinToFrame( *(mrSidebarItem.maLayoutInfo.mpAnchorFrame), + mrSidebarItem.GetFormatField(), + *this ); + } +} + +css::uno::Reference< css::accessibility::XAccessible > SwAnnotationWin::CreateAccessible() +{ + SidebarWinAccessible* pAcc( new SidebarWinAccessible( *this, + mrView.GetWrtShell(), + mrSidebarItem ) ); + css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc ); + SetWindowPeer( xWinPeer, pAcc ); + + css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY ); + return xAcc; +} + +} // 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 000000000..de46be7cd --- /dev/null +++ b/sw/source/uibase/docvw/DashedLine.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/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SwDashedLine::SwDashedLine( vcl::Window* pParent, Color& ( *pColorFn )() ) : + FixedLine( 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 pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(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 aStrokePattern; + basegfx::BColor aColor = 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 + drawinglayer::primitive2d::PolygonHairlinePrimitive2D * pPlainLine = + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon, aOtherColor); + + aSeq[0] = drawinglayer::primitive2d::Primitive2DReference(pPlainLine); + // Dashed line in twips + aStrokePattern.push_back(3); + aStrokePattern.push_back(3); + + aSeq.resize(2); + } + + // Compute the dashed line primitive + drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine = + new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + drawinglayer::attribute::LineAttribute(m_pColorFn().getBColor()), + drawinglayer::attribute::StrokeAttribute(aStrokePattern)); + + aSeq[aSeq.size() - 1] = drawinglayer::primitive2d::Primitive2DReference(pLine); + + 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 000000000..9d68bc950 --- /dev/null +++ b/sw/source/uibase/docvw/FrameControlsManager.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +SwFrameControlsManager::SwFrameControlsManager( SwEditWin* pEditWin ) : + m_pEditWin( pEditWin ), + m_aControls( ) +{ +} + +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( VclPtr::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() ); + + SwHeaderFooterWin* pWin = dynamic_cast(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( + VclPtr::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 ); + } + + SwPageBreakWin* pWin = dynamic_cast(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( + VclPtr::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(pControl->GetWindow()); + assert(pButton != nullptr); + pButton->SetOffset(aTopRightPixel); + pControl->ShowAll( bShow ); +} + +SwFrameMenuButtonBase::SwFrameMenuButtonBase( SwEditWin* pEditWin, const SwFrame* pFrame ) : + MenuButton( pEditWin, WB_DIALOGCONTROL ), + m_pEditWin( pEditWin ), + m_pFrame( pFrame ) +{ +} + +const SwPageFrame* SwFrameMenuButtonBase::GetPageFrame() const +{ + if (m_pFrame->IsPageFrame()) + return static_cast( m_pFrame ); + + if (m_pFrame->IsFlyFrame()) + return static_cast(m_pFrame)->GetAnchorFrame()->FindPageFrame(); + + return m_pFrame->FindPageFrame(); +} + +void SwFrameMenuButtonBase::dispose() +{ + m_pEditWin.clear(); + m_pFrame = nullptr; + MenuButton::dispose(); +} + +SwFrameControl::SwFrameControl( const VclPtr &pWindow ) +{ + assert(static_cast(pWindow)); + mxWindow.reset( pWindow ); + mpIFace = dynamic_cast( 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 000000000..bce5cfcde --- /dev/null +++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx @@ -0,0 +1,521 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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::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(drawinglayer::attribute::GradientStyle::Linear, 0.0, 0.0, 0.0, nAngle, aLighterColor, aFillColor, 10); + rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::FillGradientPrimitive2D(aGradientRect, aFillAttrs))); + } + + // Create the border lines primitive + rSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon, aLineColor))); +} + +SwHeaderFooterWin::SwHeaderFooterWin( SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) : + SwFrameMenuButtonBase( pEditWin, pFrame ), + m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/headerfootermenu.ui", ""), + m_bIsHeader( bHeader ), + m_pPopupMenu(m_aBuilder.get_menu("menu")), + m_pLine( nullptr ), + m_bIsAppearing( false ), + m_nFadeRate( 100 ), + m_aFadeTimer( ) +{ + //FIXME RenderContext + + // Get the font and configure it + vcl::Font aFont = Application::GetSettings().GetStyleSettings().GetToolFont(); + SetZoomedPointFont(*this, aFont); + + // Create the line control + m_pLine = VclPtr::Create(GetEditWin(), &SwViewOption::GetHeaderFooterMarkColor); + m_pLine->SetZOrder(this, ZOrderFlags::Before); + + // set the PopupMenu + // Rewrite the menu entries' text + if (m_bIsHeader) + { + m_pPopupMenu->SetItemText(m_pPopupMenu->GetItemId("edit"), SwResId(STR_FORMAT_HEADER)); + m_pPopupMenu->SetItemText(m_pPopupMenu->GetItemId("delete"), SwResId(STR_DELETE_HEADER)); + } + else + { + m_pPopupMenu->SetItemText(m_pPopupMenu->GetItemId("edit"), SwResId(STR_FORMAT_FOOTER)); + m_pPopupMenu->SetItemText(m_pPopupMenu->GetItemId("delete"), SwResId(STR_DELETE_FOOTER)); + } + + SetPopupMenu(m_pPopupMenu); + + m_aFadeTimer.SetTimeout(50); + m_aFadeTimer.SetInvokeHandler(LINK(this, SwHeaderFooterWin, FadeHandler)); +} + +SwHeaderFooterWin::~SwHeaderFooterWin( ) +{ + disposeOnce(); +} + +void SwHeaderFooterWin::dispose() +{ + m_pPopupMenu.clear(); + m_aBuilder.disposeBuilder(); + m_pLine.disposeAndClear(); + SwFrameMenuButtonBase::dispose(); +} + +void SwHeaderFooterWin::SetOffset(Point aOffset, long nXLineStart, long nXLineEnd) +{ + // Compute the text to show + const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + bool bIsFirst = !pDesc->IsFirstShared() && GetPageFrame()->OnFirstPage(); + bool bIsLeft = !pDesc->IsHeaderShared() && !GetPageFrame()->OnRightPage(); + bool bIsRight = !pDesc->IsHeaderShared() && GetPageFrame()->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()); + + // Compute the text size and get the box position & size from it + ::tools::Rectangle aTextRect; + GetTextBoundRect(aTextRect, m_sLabel); + ::tools::Rectangle aTextPxRect = LogicToPixel(aTextRect); + FontMetric aFontMetric = GetFontMetric(GetFont()); + Size aBoxSize (aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2, + aFontMetric.GetLineHeight() + TEXT_PADDING * 2 ); + + 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); + + double nYLinePos = aBoxPos.Y(); + if (!m_bIsHeader) + nYLinePos += aBoxSize.Height(); + Point aLinePos(nXLineStart, nYLinePos); + Size aLineSize(nXLineEnd - nXLineStart, 1); + m_pLine->SetPosSizePixel(aLinePos, aLineSize); +} + +void SwHeaderFooterWin::ShowAll(bool bShow) +{ + if (!PopupMenu::IsInExecute()) + { + 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()); + if (aRect.IsInside(rDocPt)) + return true; + + ::tools::Rectangle aLineRect(m_pLine->GetPosPixel(), m_pLine->GetSizePixel()); + return aLineRect.IsInside(rDocPt); +} + +void SwHeaderFooterWin::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + // 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), rRenderContext.PixelToLogic(GetSizePixel()))); + + SwFrameButtonPainter::PaintButton(aSeq, aRect, m_bIsHeader); + + // Create the text primitive + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + B2DVector aFontSize; + FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontSize, rRenderContext.GetFont(), false, false); + + FontMetric aFontMetric = rRenderContext.GetFontMetric(rRenderContext.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(), aFontAttr, css::lang::Locale(), aLineColor))); + + // Create the 'plus' or 'arrow' primitive + B2DRectangle aSignArea(B2DPoint(aRect.Right() - BUTTON_WIDTH, 0.0), + B2DSize(aRect.Right(), aRect.getHeight())); + + B2DPolygon aSign; + if (IsEmptyHeaderFooter()) + { + // 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 pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, 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(COL_WHITE.getBColor(), + 1.0 - nFadeRate); + + aGhostedSeq[0] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::ModifiedColorPrimitive2D(aSeq, aBColorModifier)); + + pProcessor->process(aGhostedSeq); +} + +bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) const +{ + bool bResult = true; + + // Actually check it + const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + + bool const bFirst(GetPageFrame()->OnFirstPage()); + const SwFrameFormat *const pFormat = (GetPageFrame()->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(const OString& rIdent) +{ + SwView& rView = GetEditWin()->GetView(); + SwWrtShell& rSh = rView.GetWrtShell(); + + const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + if (rIdent == "edit") + { + OString sPageId = m_bIsHeader ? OString("header") : OString("footer"); + rView.GetDocShell()->FormatPage(rStyleName, sPageId, rSh); + } + else if (rIdent == "borderback") + { + const SwPageDesc* pDesc = GetPageFrame()->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 aBoxInfo(std::make_shared(SID_ATTR_BORDER_INNER)); + const SfxPoolItem *pBoxInfo; + if (SfxItemState::SET == pHFFormat->GetAttrSet().GetItemState(SID_ATTR_BORDER_INNER, true, &pBoxInfo)) + aBoxInfo.reset(static_cast(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 == "delete") + { + rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, false, true ); + // warning: "this" may be disposed now + rSh.GetWin()->GrabFocusToDocument(); + } + else if (rIdent == "insert_pagenumber") + { + SfxViewFrame* pVFrame = rSh.GetView().GetViewFrame(); + pVFrame->GetBindings().Execute(FN_INSERT_FLD_PGNUMBER); + } + else if (rIdent == "insert_pagecount") + { + SfxViewFrame* pVFrame = rSh.GetView().GetViewFrame(); + pVFrame->GetBindings().Execute(FN_INSERT_FLD_PGCOUNT); + } +} + +void SwHeaderFooterWin::SetReadonly( bool bReadonly ) +{ + ShowAll( !bReadonly ); +} + +void SwHeaderFooterWin::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (IsEmptyHeaderFooter()) + { + SwView& rView = GetEditWin()->GetView(); + SwWrtShell& rSh = rView.GetWrtShell(); + + const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, true, false ); + } + else + MenuButton::MouseButtonDown( rMEvt ); +} + +void SwHeaderFooterWin::Select() +{ + ExecuteCommand(GetCurItemIdent()); +} + +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(); + m_pLine->Show(); + } + else if (m_nFadeRate == 100 && IsVisible()) + { + Show(false); + m_pLine->Show(false); + } + else + Invalidate(); + + 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/OverlayRanges.cxx b/sw/source/uibase/docvw/OverlayRanges.cxx new file mode 100644 index 000000000..e00aaa30c --- /dev/null +++ b/sw/source/uibase/docvw/OverlayRanges.cxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + const sal_uInt16 nTransparence( aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() ); + const double fTransparence( nTransparence / 100.0 ); + const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence( + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aRetval, + fTransparence)); + + if ( mbShowSolidBorder ) + { + const basegfx::BColor aRGBColor(getBaseColor().getBColor()); + const basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges())); + const drawinglayer::primitive2d::Primitive2DReference aOutline( + new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( + aPolyPolygon, + aRGBColor)); + + aRetval.resize(2); + aRetval[0] = aUnifiedTransparence; + aRetval[1] = aOutline; + } + else + { + aRetval = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparence }; + } + + return aRetval; + } + + /*static*/ std::unique_ptr OverlayRanges::CreateOverlayRange( + SwView const & rDocView, + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ) + { + std::unique_ptr pOverlayRanges; + + SdrView* pView = rDocView.GetDrawView(); + if ( pView != nullptr ) + { + SdrPaintWindow* pCandidate = pView->GetPaintWindow(0); + const rtl::Reference& xTargetOverlay = pCandidate->GetOverlayManager(); + + if ( xTargetOverlay.is() ) + { + pOverlayRanges.reset(new sw::overlay::OverlayRanges( rColor, rRanges, bShowSolidBorder )); + xTargetOverlay->add( *pOverlayRanges ); + } + } + + return pOverlayRanges; + } + + OverlayRanges::OverlayRanges( + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ) + : sdr::overlay::OverlayObject( rColor ) + , maRanges( rRanges ) + , mbShowSolidBorder( bShowSolidBorder ) + { + // no AA for highlight overlays + allowAntiAliase(false); + } + + OverlayRanges::~OverlayRanges() + { + if( getOverlayManager() ) + { + getOverlayManager()->remove(*this); + } + } + + void OverlayRanges::setRanges(const std::vector< basegfx::B2DRange >& rNew) + { + if(rNew != maRanges) + { + maRanges = 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 000000000..7482deef8 --- /dev/null +++ b/sw/source/uibase/docvw/OverlayRanges.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_DOCVW_OVERLAYRANGES_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_OVERLAYRANGES_HXX + +#include +#include + +#include + +class SwView; + +namespace sw +{ + namespace overlay + { + class OverlayRanges final : public sdr::overlay::OverlayObject + { + public: + static std::unique_ptr CreateOverlayRange( + SwView const & rDocView, + const Color& rColor, + const 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(const std::vector< basegfx::B2DRange >& rNew); + + void ShowSolidBorder(); + void HideSolidBorder(); + + private: + OverlayRanges( + const Color& rColor, + const 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 overlay +} // end of namespace sw + +#endif // INCLUDED_SW_SOURCE_UIBASE_DOCVW_OVERLAYRANGES_HXX + +/* 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 000000000..84ebedb0e --- /dev/null +++ b/sw/source/uibase/docvw/PageBreakWin.cxx @@ -0,0 +1,469 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUTTON_WIDTH 30 +#define BUTTON_HEIGHT 19 +#define ARROW_WIDTH 9 + +using namespace basegfx; +using namespace basegfx::utils; + +namespace +{ + class SwBreakDashedLine : public SwDashedLine + { + private: + VclPtr m_pWin; + + public: + SwBreakDashedLine( vcl::Window* pParent, Color& ( *pColorFn )(), SwPageBreakWin* pWin ) : + SwDashedLine( pParent, pColorFn ), + m_pWin( pWin ) {}; + virtual ~SwBreakDashedLine() override { disposeOnce(); } + virtual void dispose() override { m_pWin.clear(); SwDashedLine::dispose(); } + + virtual void MouseMove( const MouseEvent& rMEvt ) override; + }; + + 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->IsVisible() ) + { + m_pWin->Fade( true ); + } + + if ( !rMEvt.IsSynthetic() && !m_pWin->IsVisible() ) + { + m_pWin->UpdatePosition( rMEvt.GetPosPixel() ); + } + } +} + +SwPageBreakWin::SwPageBreakWin( SwEditWin* pEditWin, const SwFrame *pFrame ) : + SwFrameMenuButtonBase( pEditWin, pFrame ), + m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/pagebreakmenu.ui", ""), + m_pPopupMenu(m_aBuilder.get_menu("menu")), + m_pLine( nullptr ), + m_bIsAppearing( false ), + m_nFadeRate( 100 ), + m_nDelayAppearing( 0 ), + m_bDestroyed( false ) +{ + // Use pixels for the rest of the drawing + SetMapMode( MapMode ( MapUnit::MapPixel ) ); + + // Create the line control + m_pLine = VclPtr::Create( GetEditWin(), &SwViewOption::GetPageBreakColor, this ); + + // Set the popup menu + m_pPopupMenu->SetDeactivateHdl( LINK( this, SwPageBreakWin, HideHandler ) ); + SetPopupMenu(m_pPopupMenu); + + m_aFadeTimer.SetTimeout( 50 ); + m_aFadeTimer.SetInvokeHandler( LINK( this, SwPageBreakWin, FadeHandler ) ); +} + +SwPageBreakWin::~SwPageBreakWin( ) +{ + disposeOnce(); +} + +void SwPageBreakWin::dispose() +{ + m_bDestroyed = true; + m_aFadeTimer.Stop(); + + m_pLine.disposeAndClear(); + m_pPopupMenu.clear(); + m_aBuilder.disposeBuilder(); + + SwFrameMenuButtonBase::dispose(); +} + +void SwPageBreakWin::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + const ::tools::Rectangle aRect(::tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel()))); + + // Properly paint the control + BColor aColor = SwViewOption::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( + 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.getHeight()) / 2.0; + double nBottom = nTop + 4.0; + double nLeft = aRect.getWidth() - 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(COL_WHITE.getBColor(), + 1.0 - nFadeRate); + aGhostedSeq[0].set( new drawinglayer::primitive2d::ModifiedColorPrimitive2D( + aSeq, aBColorModifier)); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + std::unique_ptr pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos)); + + pProcessor->process(aGhostedSeq); +} + +void SwPageBreakWin::Select() +{ + SwFrameControlPtr pThis = GetEditWin()->GetFrameControlsManager( ).GetControl( FrameControlType::PageBreak, GetFrame() ); + + OString sIdent = GetCurItemIdent(); + if (sIdent == "edit") + { + const SwLayoutFrame* pBodyFrame = static_cast< const SwLayoutFrame* >( GetPageFrame()->Lower() ); + while ( pBodyFrame && !pBodyFrame->IsBodyFrame() ) + pBodyFrame = static_cast< const SwLayoutFrame* >( pBodyFrame->GetNext() ); + + SwEditWin* pEditWin = GetEditWin(); + + if ( pBodyFrame ) + { + SwWrtShell& rSh = pEditWin->GetView().GetWrtShell(); + bool bOldLock = rSh.IsViewLocked(); + rSh.LockView( true ); + + if ( pBodyFrame->Lower()->IsTabFrame() ) + { + rSh.Push( ); + rSh.ClearMark(); + + SwContentFrame *pCnt = const_cast< SwContentFrame* >( pBodyFrame->ContainsContent() ); + SwContentNode* pNd = pCnt->IsTextFrame() + ? static_cast(pCnt)->GetTextNodeFirst() + : static_cast(pCnt)->GetNode(); + rSh.SetSelection( *pNd ); + + SfxStringItem aItem(pEditWin->GetView().GetPool().GetWhich(FN_FORMAT_TABLE_DLG), "textflow"); + pEditWin->GetView().GetViewFrame()->GetDispatcher()->ExecuteList( + FN_FORMAT_TABLE_DLG, + SfxCallMode::SYNCHRON | SfxCallMode::RECORD, + { &aItem }); + + rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); + } + else + { + SwContentFrame *pCnt = const_cast< SwContentFrame* >( pBodyFrame->ContainsContent() ); + SwContentNode* pNd = pCnt->IsTextFrame() + ? static_cast(pCnt)->GetTextNodeFirst() + : static_cast(pCnt)->GetNode(); + + SwPaM aPaM( *pNd ); + SwPaMItem aPaMItem( pEditWin->GetView().GetPool( ).GetWhich( FN_PARAM_PAM ), &aPaM ); + SfxStringItem aItem( pEditWin->GetView().GetPool( ).GetWhich( SID_PARA_DLG ), "textflow" ); + pEditWin->GetView().GetViewFrame()->GetDispatcher()->ExecuteList( + SID_PARA_DLG, + SfxCallMode::SYNCHRON | SfxCallMode::RECORD, + { &aItem, &aPaMItem }); + } + rSh.LockView( bOldLock ); + pEditWin->GrabFocus( ); + } + } + else if (sIdent == "delete") + { + const SwLayoutFrame* pBodyFrame = static_cast< const SwLayoutFrame* >( GetPageFrame()->Lower() ); + while ( pBodyFrame && !pBodyFrame->IsBodyFrame() ) + pBodyFrame = static_cast< const SwLayoutFrame* >( pBodyFrame->GetNext() ); + + if ( pBodyFrame ) + { + + SwContentFrame *pCnt = const_cast< SwContentFrame* >( pBodyFrame->ContainsContent() ); + SwContentNode* pNd = pCnt->IsTextFrame() + ? static_cast(pCnt)->GetTextNodeFirst() + : static_cast(pCnt)->GetNode(); + + pNd->GetDoc()->GetIDocumentUndoRedo( ).StartUndo( SwUndoId::UI_DELETE_PAGE_BREAK, nullptr ); + + SfxItemSet aSet( + GetEditWin()->GetView().GetWrtShell().GetAttrPool(), + svl::Items{}); + aSet.Put( SvxFormatBreakItem( SvxBreak::NONE, RES_BREAK ) ); + aSet.Put( SwFormatPageDesc( nullptr ) ); + + SwPaM aPaM( *pNd ); + pNd->GetDoc()->getIDocumentContentOperations().InsertItemSet( + aPaM, aSet, SetAttrMode::DEFAULT, GetPageFrame()->getRootFrame()); + + pNd->GetDoc()->GetIDocumentUndoRedo( ).EndUndo( SwUndoId::UI_DELETE_PAGE_BREAK, nullptr ); + } + } + + // Only fade if there is more than this temporary shared pointer: + // The main reference has been deleted due to a page break removal + if ( pThis.use_count() > 1 ) + Fade( false ); +} + +void SwPageBreakWin::MouseMove( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeaveWindow() ) + { + // don't fade if we just move to the 'line', or the popup menu is open + Point aEventPos( rMEvt.GetPosPixel() + rMEvt.GetPosPixel() ); + if ( !Contains( aEventPos ) && !PopupMenu::IsInExecute() ) + Fade( false ); + } + else if ( !IsVisible() ) + Fade( true ); +} + +void SwPageBreakWin::Activate( ) +{ + Fade( true ); + MenuButton::Activate(); +} + +void SwPageBreakWin::UpdatePosition(const std::optional& xEvtPt) +{ + if ( xEvtPt ) + { + if ( xEvtPt == m_xMousePt ) + return; + m_xMousePt = xEvtPt; + } + + const SwPageFrame* pPageFrame = GetPageFrame(); + 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()).SVRect() ); + ::tools::Rectangle aFrameRect = GetEditWin()->LogicToPixel( pPageFrame->getFrameArea().SVRect() ); + + 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 + long nPgLeft = aFrameRect.Left(); + long nPgRight = aFrameRect.Right(); + + unsigned long 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() ); + + long nLineLeft = std::max( nPgLeft, aVisArea.Left() ); + long nLineRight = std::min( nPgRight, aVisArea.Right() ); + 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 + Point aBtnPos( nBtnLeft, nYLineOffset - BUTTON_HEIGHT / 2 ); + SetPosSizePixel( aBtnPos, aBtnSize ); + + // Set the line position + Point aLinePos( nLineLeft, nYLineOffset - 5 ); + Size aLineSize( nLineRight - nLineLeft, 10 ); + m_pLine->SetPosSizePixel( aLinePos, aLineSize ); +} + +void SwPageBreakWin::ShowAll( bool bShow ) +{ + m_pLine->Show( bShow ); +} + +bool SwPageBreakWin::Contains( const Point &rDocPt ) const +{ + ::tools::Rectangle aRect( GetPosPixel(), GetSizePixel() ); + if ( aRect.IsInside( rDocPt ) ) + return true; + + ::tools::Rectangle aLineRect( m_pLine->GetPosPixel(), m_pLine->GetSizePixel() ); + return aLineRect.IsInside( rDocPt ); +} + +void SwPageBreakWin::SetReadonly( bool bReadonly ) +{ + ShowAll( !bReadonly ); +} + +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_NOARG(SwPageBreakWin, HideHandler, Menu *, bool) +{ + Fade( false ); + + return false; +} + +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(); + else + { + UpdatePosition(); + Invalidate(); + } + + 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/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx new file mode 100644 index 000000000..b67252a13 --- /dev/null +++ b/sw/source/uibase/docvw/PostItMgr.cxx @@ -0,0 +1,2456 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include +#include "frmsidebarwincontainer.hxx" +#include + +#include +#include "AnchorOverlayObject.hxx" +#include "ShadowOverlayObject.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// 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& a, const std::unique_ptr& 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.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() ) + aAnchorAInFooter = true; + if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.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->pPostIt.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 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("parent", pWin->CalcParent()); + 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, aPayload.c_str()); + } + } + +} // 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) + , mpAnswer(nullptr) + , 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()); + 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(); + EndListening( *mpView->GetDocShell() ); + + mPages.clear(); +} + +void 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(*(*it)->GetBroadcaster())); + std::unique_ptr p = std::move(*it); + it = mvPostItFields.erase(it); + if (GetActiveSidebarWin() == p->pPostIt) + SetActiveSidebarWin(nullptr); + p->pPostIt.disposeAndClear(); + bRemoved = true; + } + else + ++it; + } + + if ( bRemoved ) + { + // make sure that no deleted items remain in page lists + // todo: only remove deleted ones?! + if ( mvPostItFields.empty() ) + { + PreparePageContainer(); + PrepareView(); + } + else + // if postits are their make sure that page lists are not empty + // otherwise sudden paints can cause pain (in BorderOverPageBorder) + CalcRects(); + } +} + +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 (dynamic_cast< const SwFormatField *>( pItem ) != nullptr) + { + mvPostItFields.push_back(std::make_unique(static_cast(*pItem), bFocus)); + pAnnotationItem = mvPostItFields.back().get(); + } + OSL_ENSURE(dynamic_cast< const SwFormatField *>( pItem ) != nullptr,"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& pField) { return pField->GetBroadcaster() == pBroadcast; }); + if (i != mvPostItFields.end()) + { + std::unique_ptr 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->pPostIt) + SetActiveSidebarWin(nullptr); + p->pPostIt.disposeAndClear(); + } + mbLayout = true; + PrepareView(); +} + +void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if ( const SfxEventHint* pSfxEventHint = dynamic_cast(&rHint) ) + { + if ( pSfxEventHint->GetEventId() == SfxEventHintId::SwEventLayoutFinished ) + { + if ( !mbWaitingForCalcRects && !mvPostItFields.empty()) + { + mbWaitingForCalcRects = true; + mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl) ); + } + } + } + else if ( const SwFormatFieldHint * pFormatHint = dynamic_cast(&rHint) ) + { + SwFormatField* pField = const_cast ( 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->bPendingLayout = true; + } + else + { + OSL_FAIL("Inserted field not in document!" ); + } + break; + } + case SwFormatFieldHintWhich::REMOVED: + { + if (mbDeleteNote) + { + if (!pField) + { + CheckForRemovedPostIts(); + break; + } + RemoveItem(pField); + + // If LOK has disabled tiled annotations, emit annotation callbacks + if (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations()) + { + SwPostItField* pPostItField = static_cast(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(&rBC); + for (auto const& postItField : mvPostItFields) + { + if ( pFormatField == postItField->GetBroadcaster() ) + { + if (postItField->pPostIt) + { + postItField->pPostIt->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; + } + + case SwFormatFieldHintWhich::LANGUAGE: + { + SwFormatField* pFormatField = dynamic_cast(&rBC); + for (auto const& postItField : mvPostItFields) + { + if ( pFormatField == postItField->GetBroadcaster() ) + { + if (postItField->pPostIt) + { + const SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( postItField->GetFormatField().GetField()->GetLanguage() ); + sal_uInt16 nLangWhichId = 0; + 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: break; + } + postItField->pPostIt->SetLanguage( + SvxLanguageItem( + postItField->GetFormatField().GetField()->GetLanguage(), + nLangWhichId) ); + } + break; + } + } + break; + } + } + } + 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::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(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->pPostIt) + { + postItField->pPostIt->GrabFocus(); + MakeVisible(postItField->pPostIt); + } + else + { + // when the layout algorithm starts, this postit is created and receives focus + postItField->bFocus = 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 sal_uLong 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->pPostIt) + pItem->pPostIt->HideNote(); + continue; + } + + if( SwPostItHelper::HIDDEN == pItem->mLayoutStatus ) + { + if (!mpWrtShell->GetViewOptions()->IsShowHiddenChar()) + { + if (pItem->pPostIt) + pItem->pPostIt->HideNote(); + continue; + } + } + + const unsigned long aPageNum = pItem->maLayoutInfo.mnPageNumber; + if (aPageNum > mPages.size()) + { + const unsigned long nNumberOfPages = mPages.size(); + mPages.reserve(aPageNum); + for (unsigned long j=0; jmvSidebarItems.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)) + { + 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->bShow && postItField->pPostIt && postItField->pPostIt->HasScrollbar()) + return true; + } + return false; +} + +void SwPostItMgr::PreparePageContainer() +{ + // we do not just delete the SwPostItPageItem, so offset/scrollbar is not lost + long lPageSize = mpWrtShell->GetNumPages(); + long lContainerSize = mPages.size(); + + if (lContainerSize < lPageSize) + { + mPages.reserve(lPageSize); + for (long i=0; i 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() +{ + bool bEnableMapMode = comphelper::LibreOfficeKit::isActive() && !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& pPage : mPages) + { + // only layout if there are notes on this page + if (!pPage->mvSidebarItems.empty()) + { + std::vector aVisiblePostItList; + unsigned long lNeededHeight = 0; + long mlPageBorder = 0; + long mlPageEnd = 0; + + for (auto const& pItem : pPage->mvSidebarItems) + { + VclPtr pPostIt = pItem->pPostIt; + + 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; + } + + if (pItem->bShow) + { + long Y = mpEditWin->LogicToPixel( Point(0,pItem->maLayoutInfo.mPosition.Bottom())).Y(); + long aPostItHeight = 0; + if (!pPostIt) + { + pPostIt = pItem->GetSidebarWindow( mpView->GetEditWin(), + *this ); + pPostIt->InitControls(); + pPostIt->SetReadonly(mbReadOnly); + pItem->pPostIt = pPostIt; + if (mpAnswer) + { + if (static_cast(pPostIt->CalcParent())) //do we really have another note in front of this one + pPostIt->InitAnswer(mpAnswer); + delete mpAnswer; + mpAnswer = nullptr; + } + } + + pPostIt->SetChangeTracking( + pItem->mLayoutStatus, + GetColorAnchor(pItem->maLayoutInfo.mRedlineAuthor)); + pPostIt->SetSidebarPosition(pPage->eSidebarPosition); + pPostIt->SetFollow(static_cast(pPostIt->CalcParent())); + aPostItHeight = ( pPostIt->GetPostItTextHeight() < pPostIt->GetMinimumSizeWithoutMeta() + ? pPostIt->GetMinimumSizeWithoutMeta() + : pPostIt->GetPostItTextHeight() ) + + pPostIt->GetMetaHeight(); + pPostIt->SetPosSizePixelRect( mlPageBorder , + Y - GetInitialAnchorDistance(), + GetSidebarWidth(true), + aPostItHeight, + pItem->maLayoutInfo.mPosition, + mlPageEnd ); + pPostIt->ChangeSidebarItem( *pItem ); + + if (pItem->bFocus) + { + mbLayout = true; + pPostIt->GrabFocus(); + pItem->bFocus = false; + } + // only the visible postits are used for the final layout + aVisiblePostItList.push_back(pPostIt); + 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; + if (ShowNotes()) + pPage->bScrollbar = LayoutByPage(aVisiblePostItList, pPage->mPageRect.SVRect(), lNeededHeight); + else + pPage->bScrollbar = false; + 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 + long aAvailableHeight = mpEditWin->LogicToPixel(Size(0,pPage->mPageRect.Height())).Height() - 2 * GetSidebarScrollerHeight(); + long lOffset = -1 * nScrollSize * (aVisiblePostItList.size() - aAvailableHeight / nScrollSize); + if (pPage->lOffset < lOffset) + pPage->lOffset = lOffset; + } + bUpdate = (bOldScrollbar != pPage->bScrollbar) || bUpdate; + const 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); + visiblePostIt->InvalidateControl(); + } + } + 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 (comphelper::LibreOfficeKit::isActive() && !comphelper::LibreOfficeKit::isTiledAnnotations()) + { + if (visiblePostIt->GetSidebarItem().bPendingLayout) + 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().bPendingLayout = false; + } + } + else + { + if (pPage->bScrollbar) + bUpdate = true; + pPage->bScrollbar = false; + } + } + + if (!ShowNotes()) + { // 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->pPostIt) + { + postItField->pPostIt->HideNote(); + if (postItField->pPostIt->HasChildPathFocus()) + { + SetActiveSidebarWin(nullptr); + postItField->pPostIt->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(unsigned long 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)->pPostIt,"BorderOverPageBorder: NULL postIt, should never happen"); + if ((*aItem)->pPostIt) + { + const long aSidebarheight = mPages[aPage-1]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0; + const long aEndValue = mpEditWin->PixelToLogic(Point(0,(*aItem)->pPostIt->GetPosPixel().Y()+(*aItem)->pPostIt->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->pPostIt; + if (!pPostIt) + continue; + Point aPoint(mpEditWin->PixelToLogic(pPostIt->GetPosPixel())); + pPostIt->Draw(pOutDev, aPoint, DrawFlags::NONE); + } +} + +void SwPostItMgr::PaintTile(OutputDevice& rRenderContext) +{ + for (const std::unique_ptr& pItem : mvPostItFields) + { + SwAnnotationWin* pPostIt = pItem->pPostIt; + if (!pPostIt) + continue; + + bool bEnableMapMode = !mpEditWin->IsMapModeEnabled(); + mpEditWin->EnableMapMode(); + rRenderContext.Push(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 long lScroll,const unsigned long 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 long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height(); + for (auto const& item : mPages[aPage-1]->mvSidebarItems) + { + SwAnnotationWin* pPostIt = item->pPostIt; + // 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->bShow) + { + 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 unsigned long aPage ) +{ + // otherwise all notes are visible + if (mPages[aPage-1]->bScrollbar) + { + const 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 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 long lScroll = bBottom ? (aDiff + ( nScrollSize - (aDiff % nScrollSize))) : (aDiff - (nScrollSize + (aDiff % nScrollSize))); + Scroll(lScroll, aPage); + } + } +} + +void SwPostItMgr::MakeVisible(const SwAnnotationWin* pPostIt ) +{ + long aPage = -1; + // we don't know the page yet, lets find it ourselves + std::vector::size_type n=0; + for (auto const& page : mPages) + { + for (auto const& item : page->mvSidebarItems) + { + if (item->pPostIt==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,unsigned long 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,unsigned long 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 &aVisiblePostItList, const tools::Rectangle& rBorder, 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); + long lTopBorder = aBorder.Top() + 5; + long lBottomBorder = aBorder.Bottom() - 5; + const long lVisibleHeight = lBottomBorder - lTopBorder; //aBorder.GetHeight() ; + const size_t nPostItListSize = aVisiblePostItList.size(); + 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 long lAverageHeight = (lVisibleHeight - nPostItListSize*GetSpaceBetween()) / nPostItListSize; + if (lAverageHeightSetSize(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; + 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 + { + 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()) + { + 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 vFormatFields; + pType->CollectPostIts(vFormatFields, rIDRA, mpWrtShell->GetLayout()->IsHideRedlines()); + 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(postItField->GetBroadcaster()) ); + postItField->pPostIt.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(const OUString &rAuthor) + : m_sAuthor(rAuthor) + { + } + bool operator()(const SwFormatField* pField) const override + { + if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit) + return false; + return static_cast(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(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>& sidebarItemVector; + std::vector v; + SwDocShell& m_rDocShell; + FilterFunctor& m_rFilter; + + virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override + { + const SwFormatFieldHint* pHint = dynamic_cast(&rHint); + if (pHint) + { + bool bAllInvalidated = false; + if (pHint->Which() == SwFormatFieldHintWhich::REMOVED) + { + const SwFormatField* pField = pHint->GetField(); + bAllInvalidated = pField == nullptr; + if (!bAllInvalidated && m_rFilter(pField)) + { + EndListening(const_cast(*pField)); + v.erase(std::remove(v.begin(), v.end(), pField), v.end()); + } + } + else if (pHint->Which() == SwFormatFieldHintWhich::INSERTED) + { + const SwFormatField* pField = pHint->GetField(); + bAllInvalidated = pField == nullptr; + if (!bAllInvalidated && m_rFilter(pField)) + { + StartListening(const_cast(*pField)); + v.push_back(pField); + } + } + + if (bAllInvalidated) + FillVector(); + + return; + } + } + +public: + FieldDocWatchingStack(std::vector>& in, SwDocShell &rDocShell, FilterFunctor& rFilter) + : sidebarItemVector(in) + , m_rDocShell(rDocShell) + , m_rFilter(rFilter) + { + FillVector(); + StartListening(m_rDocShell); + } + void FillVector() + { + EndListeningToAllFields(); + v.clear(); + v.reserve(sidebarItemVector.size()); + for (auto const& p : sidebarItemVector) + { + const SwFormatField& rField = p->GetFormatField(); + if (!m_rFilter(&rField)) + continue; + StartListening(const_cast(rField)); + v.push_back(&rField); + } + } + void EndListeningToAllFields() + { + for (auto const& pField : v) + { + EndListening(const_cast(*pField)); + } + } + virtual ~FieldDocWatchingStack() override + { + EndListeningToAllFields(); + EndListening(m_rDocShell); + } + const SwFormatField* pop() + { + if (v.empty()) + return nullptr; + const SwFormatField* p = v.back(); + EndListening(const_cast(*p)); + v.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::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->pPostIt; + if (pWin) + break; + } + } + if (!pWin) + return; + SetActiveSidebarWin(pWin); + OutlinerView* pOLV = pWin->GetOutlinerView(); + SfxItemSet aEditAttr(pOLV->GetAttribs()); + SfxItemPool* pPool(SwAnnotationShell::GetAnnotationPool(rView)); + SfxItemSet aDlgAttr(*pPool, svl::Items{}); + aDlgAttr.Put(aEditAttr); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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->pPostIt) + continue; + OutlinerView* pOLV = postItField->pPostIt->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->pPostIt->UpdateData(); + } + + mpWrtShell->EndUndo(); + PrepareView(); + mpWrtShell->EndAllAction(); + mbLayout = true; + CalcRects(); + LayoutPostIts(); +} + +void SwPostItMgr::Hide( const OUString& rAuthor ) +{ + for (auto const& postItField : mvPostItFields) + { + if ( postItField->pPostIt && (postItField->pPostIt->GetAuthor() == rAuthor) ) + { + postItField->bShow = false; + postItField->pPostIt->HideNote(); + } + } + + LayoutPostIts(); +} + +void SwPostItMgr::Hide() +{ + for (auto const& postItField : mvPostItFields) + { + postItField->bShow = false; + postItField->pPostIt->HideNote(); + } +} + +void SwPostItMgr::Show() +{ + for (auto const& postItField : mvPostItFields) + { + postItField->bShow = true; + } + LayoutPostIts(); +} + +SwAnnotationWin* SwPostItMgr::GetSidebarWin( const SfxBroadcaster* pBroadcaster) const +{ + for (auto const& postItField : mvPostItFields) + { + if ( postItField->GetBroadcaster() == pBroadcaster) + return postItField->pPostIt; + } + return nullptr; +} + +sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const SwPostItField* pField) const +{ + for (auto const& postItField : mvPostItFields) + { + if ( postItField->GetFormatField().GetField() == pField ) + return postItField->pPostIt.get(); + } + return nullptr; +} + +sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const sal_uInt32 nPostItId) const +{ + for (auto const& postItField : mvPostItFields) + { + if ( static_cast(postItField->GetFormatField().GetField())->GetPostItId() == nPostItId ) + return postItField->pPostIt.get(); + } + return nullptr; +} + +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& pField) { return pField->pPostIt == 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)->pPostIt == aPostIt) + return nullptr; + return (*iNextPostIt)->pPostIt; + } + else + return nullptr; +} + +long SwPostItMgr::GetNextBorder() +{ + for (auto const& pPage : mPages) + { + for(auto b = pPage->mvSidebarItems.begin(); b!= pPage->mvSidebarItems.end(); ++b) + { + if ((*b)->pPostIt == mpActivePostIt) + { + auto aNext = b; + ++aNext; + bool bFollow = (aNext != pPage->mvSidebarItems.end()) && (*aNext)->pPostIt->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)->pPostIt->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 unsigned long 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 unsigned long 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.IsInside(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& pItem : mvPostItFields) + { + SwAnnotationWin* pPostIt = pItem->pPostIt; + if (!pPostIt) + continue; + + if (pPostIt->IsHitWindow(rPointLogic)) + { + pRet = pPostIt; + break; + } + } + + if (bEnableMapMode) + mpEditWin->EnableMapMode(false); + } + + return pRet; +} + +tools::Rectangle SwPostItMgr::GetBottomScrollRect(const unsigned long 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 unsigned long 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 unsigned long 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.IsInside(aPoint)) + { + if (aPoint.X() < long((aPointBottom.X() + GetSidebarWidth()/3))) + Scroll( GetScrollSize(),aPage); + else + Scroll( -1*GetScrollSize(), aPage); + return true; + } + else if (aRectTop.IsInside(aPoint)) + { + if (aPoint.X() < 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->pPostIt; + 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 long aAnchorX = pFirstPostIt->Anchor() + ? mpEditWin->LogicToPixel( Point(static_cast(pFirstPostIt->Anchor()->GetSixthPosition().getX()),0)).X() + : 0; + const long aAnchorY = pFirstPostIt->Anchor() + ? mpEditWin->LogicToPixel( Point(0,static_cast(pFirstPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1 + : 0; + if (Point(aAnchorX,aAnchorY) != pFirstPostIt->GetPosPixel()) + { + long aAnchorPosX = 0; + long aAnchorPosY = 0; + for (const std::unique_ptr& pPage : mPages) + { + for (auto const& item : pPage->mvSidebarItems) + { + // check, if anchor overlay object exists. + if ( item->bShow && item->pPostIt && item->pPostIt->Anchor() ) + { + aAnchorPosX = pPage->eSidebarPosition == sw::sidebarwindows::SidebarPosition::LEFT + ? mpEditWin->LogicToPixel( Point(static_cast(item->pPostIt->Anchor()->GetSeventhPosition().getX()),0)).X() + : mpEditWin->LogicToPixel( Point(static_cast(item->pPostIt->Anchor()->GetSixthPosition().getX()),0)).X(); + aAnchorPosY = mpEditWin->LogicToPixel( Point(0,static_cast(item->pPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1; + item->pPostIt->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(); +} + +unsigned long 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; + } + unsigned long aWidth = static_cast(nZoom * 1.8); + + if (bPx) + return aWidth; + else + { + if (bEnableMapMode) + // The output device is the window. + mpWrtShell->GetOut()->EnableMapMode(); + long nRet = mpWrtShell->GetOut()->PixelToLogic(Size(aWidth, 0)).Width(); + if (bEnableMapMode) + mpWrtShell->GetOut()->EnableMapMode(false); + return nRet; + } +} + +unsigned long 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 ) + { + // 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->pPostIt ) + postItField->pPostIt->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->pPostIt ) + postItField->pPostIt->SetSpellChecking(); +} + +void SwPostItMgr::SetReadOnlyState() +{ + for (auto const& postItField : mvPostItFields) + if ( postItField->pPostIt ) + postItField->pPostIt->SetReadonly( mbReadOnly ); +} + +void SwPostItMgr::CheckMetaText() +{ + for (auto const& postItField : mvPostItFields) + if ( postItField->pPostIt ) + postItField->pPostIt->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() +{ + // deselect any drawing or frame and leave editing mode + SdrView* pSdrView = mpWrtShell->GetDrawView(); + if ( pSdrView && pSdrView->IsTextEdit() ) + { + bool bLockView = mpWrtShell->IsViewLocked(); + mpWrtShell->LockView( true ); + mpWrtShell->EndTextEdit(); + mpWrtShell->LockView( bLockView ); + } + + if( mpWrtShell->IsSelFrameMode() || mpWrtShell->IsObjSelected()) + { + mpWrtShell->UnSelectFrame(); + mpWrtShell->LeaveSelFrameMode(); + mpWrtShell->GetView().LeaveDrawCreate(); + mpWrtShell->EnterStdMode(); + + mpWrtShell->DrawSelChanged(); + mpView->StopShellTimer(); + } +} + +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(); + } +} + +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 ); + } + } +} + +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)->pPostIt->IsThreadResolved()) + { + (*b)->pPostIt->SetResolved(true); + (*b)->pPostIt->GetSidebarItem().bShow = 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)->pPostIt->GetTopReplyNote() == topNote) { + (*b)->pPostIt->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 000000000..65ccda759 --- /dev/null +++ b/sw/source/uibase/docvw/ShadowOverlayObject.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 "ShadowOverlayObject.hxx" + +#include +#include +#include +#include + +#include +#include +#include + +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) + : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), + 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()))); + const ::drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GradientStyle::Linear, + 0.0, + 0.5, + 0.5, + F_PI, + 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), + 2); + + rContainer.push_back( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + aFillGradientAttribute)); + break; + } + case SS_VIEW: + { + aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit()))); + const drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GradientStyle::Linear, + 0.0, + 0.5, + 0.5, + F_PI, + 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), + 4); + + rContainer.push_back( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + aFillGradientAttribute)); + break; + } + case SS_EDIT: + { + aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit()))); + const drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GradientStyle::Linear, + 0.0, + 0.5, + 0.5, + F_PI, + 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), + 4); + + rContainer.push_back( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + 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; +} + +ImplPrimitive2DIDBlock(ShadowPrimitive, PRIMITIVE2D_ID_SWSIDEBARSHADOWPRIMITIVE) + +/* static */ std::unique_ptr ShadowOverlayObject::CreateShadowOverlayObject( SwView const & rDocView ) +{ + std::unique_ptr 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 000000000..b9af12c58 --- /dev/null +++ b/sw/source/uibase/docvw/ShadowOverlayObject.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_DOCVW_SHADOWOVERLAYOBJECT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_SHADOWOVERLAYOBJECT_HXX + +#include + +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 CreateShadowOverlayObject( SwView const & rDocView ); +}; + +} // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarScrollBar.cxx b/sw/source/uibase/docvw/SidebarScrollBar.cxx new file mode 100644 index 000000000..c7e2978af --- /dev/null +++ b/sw/source/uibase/docvw/SidebarScrollBar.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/. + */ + +#include "SidebarScrollBar.hxx" + +#include + +#include +#include +#include +#include + +namespace sw::sidebarwindows +{ +SidebarScrollBar::SidebarScrollBar(sw::annotation::SwAnnotationWin& rSidebarWin, WinBits nStyle, + SwView& rView) + : ScrollBar(&rSidebarWin, nStyle) + , m_rSidebarWin(rSidebarWin) + , m_rView(rView) +{ +} + +void SidebarScrollBar::LogicInvalidate(const tools::Rectangle* pRectangle) +{ + tools::Rectangle aRectangle; + + if (!pRectangle) + { + Push(PushFlags::MAPMODE); + EnableMapMode(); + MapMode aMapMode = GetMapMode(); + aMapMode.SetMapUnit(MapUnit::MapTwip); + SetMapMode(aMapMode); + aRectangle = tools::Rectangle(Point(0, 0), PixelToLogic(GetSizePixel())); + Pop(); + } + else + aRectangle = *pRectangle; + + // Convert from relative twips to absolute ones. + vcl::Window& rParent = m_rSidebarWin.EditWin(); + Point aOffset(GetOutOffXPixel() - rParent.GetOutOffXPixel(), + GetOutOffYPixel() - rParent.GetOutOffYPixel()); + rParent.Push(PushFlags::MAPMODE); + rParent.EnableMapMode(); + aOffset = rParent.PixelToLogic(aOffset); + rParent.Pop(); + aRectangle.Move(aOffset.getX(), aOffset.getY()); + + OString sRectangle = aRectangle.toString(); + SwWrtShell& rWrtShell = m_rView.GetWrtShell(); + SfxLokHelper::notifyInvalidation(rWrtShell.GetSfxViewShell(), sRectangle); +} + +void SidebarScrollBar::MouseButtonUp(const MouseEvent& /*rMouseEvent*/) { EndTracking(); } + +void SidebarScrollBar::MouseMove(const MouseEvent& rMouseEvent) +{ + TrackingEvent aEvent(rMouseEvent); + Tracking(aEvent); +} + +SidebarScrollBar::~SidebarScrollBar() { disposeOnce(); } + +} // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarScrollBar.hxx b/sw/source/uibase/docvw/SidebarScrollBar.hxx new file mode 100644 index 000000000..2fb1a90de --- /dev/null +++ b/sw/source/uibase/docvw/SidebarScrollBar.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/. + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_DOCVW_SIDEBARSCROLLBAR_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_SIDEBARSCROLLBAR_HXX + +#include + +class SwView; + +namespace sw +{ +namespace annotation +{ +class SwAnnotationWin; +} +} + +namespace sw +{ +namespace sidebarwindows +{ +/// Similar to the VCL scrollbar, but instrumented with Writer-specific details for LOK. +class SidebarScrollBar : public ScrollBar +{ + sw::annotation::SwAnnotationWin& m_rSidebarWin; + SwView& m_rView; + +protected: + /// @see Window::LogicInvalidate(). + void LogicInvalidate(const tools::Rectangle* pRectangle) override; + void MouseMove(const MouseEvent& rMouseEvent) override; + void MouseButtonUp(const MouseEvent& rMouseEvent) override; + +public: + SidebarScrollBar(sw::annotation::SwAnnotationWin& rSidebarWin, WinBits nStyle, SwView& rView); + ~SidebarScrollBar() override; +}; +} +} + +#endif + +/* 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 000000000..65c67d098 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.cxx @@ -0,0 +1,446 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "SidebarTxtControl.hxx" + +#include "SidebarTxtControlAcc.hxx" +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace sw::sidebarwindows { + +SidebarTextControl::SidebarTextControl( sw::annotation::SwAnnotationWin& rSidebarWin, + WinBits nBits, + SwView& rDocView, + SwPostItMgr& rPostItMgr ) + : Control( &rSidebarWin, nBits ) + , mrSidebarWin( rSidebarWin ) + , mrDocView( rDocView ) + , mrPostItMgr( rPostItMgr ) +{ + AddEventListener( LINK( &mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener ) ); +} + +SidebarTextControl::~SidebarTextControl() +{ + disposeOnce(); +} + +void SidebarTextControl::dispose() +{ + RemoveEventListener( LINK( &mrSidebarWin, sw::annotation::SwAnnotationWin, WindowEventListener ) ); + Control::dispose(); +} + +OutlinerView* SidebarTextControl::GetTextView() const +{ + return mrSidebarWin.GetOutlinerView(); +} + +void SidebarTextControl::GetFocus() +{ + Window::GetFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTextControl::LoseFocus() +{ + // write the visible text back into the SwField + mrSidebarWin.UpdateData(); + + Window::LoseFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTextControl::RequestHelp(const HelpEvent &rEvt) +{ + const char* pResId = nullptr; + switch( mrSidebarWin.GetLayoutStatus() ) + { + case SwPostItHelper::INSERTED: pResId = STR_REDLINE_INSERT; break; + case SwPostItHelper::DELETED: pResId = STR_REDLINE_DELETE; break; + default: pResId = nullptr; + } + + 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() ); + Help::ShowQuickHelp( this,PixelToLogic(tools::Rectangle(rEvt.GetMousePosPixel(),Size(50,10))),sText); + } +} + +void SidebarTextControl::Draw(OutputDevice* pDev, const Point& rPt, DrawFlags) +{ + //Take the control's height, but overwrite the scrollbar area if there was one + Size aSize(PixelToLogic(GetSizePixel())); + + if ( GetTextView() ) + { + GetTextView()->GetOutliner()->Draw(pDev, tools::Rectangle(rPt, aSize)); + } + + if ( mrSidebarWin.GetLayoutStatus()==SwPostItHelper::DELETED ) + { + SetLineColor(mrSidebarWin.GetChangeColor()); + pDev->DrawLine( PixelToLogic( GetPosPixel(), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(), + GetSizePixel().Height() ), pDev->GetMapMode() ) ); + pDev->DrawLine( PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(),0), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( 0, GetSizePixel().Height() ), pDev->GetMapMode() ) ); + } +} + +void SidebarTextControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + if (!rRenderContext.GetSettings().GetStyleSettings().GetHighContrastMode()) + { + if (mrSidebarWin.IsMouseOverSidebarWin() || HasFocus()) + { + rRenderContext.DrawGradient(tools::Rectangle(Point(0,0), rRenderContext.PixelToLogic(GetSizePixel())), + Gradient(GradientStyle::Linear, mrSidebarWin.ColorDark(), mrSidebarWin.ColorDark())); + } + else + { + rRenderContext.DrawGradient(tools::Rectangle(Point(0,0), rRenderContext.PixelToLogic(GetSizePixel())), + Gradient(GradientStyle::Linear, mrSidebarWin.ColorLight(), mrSidebarWin.ColorDark())); + } + } + + if (GetTextView()) + { + GetTextView()->Paint(rRect, &rRenderContext); + } + + if (mrSidebarWin.GetLayoutStatus() == SwPostItHelper::DELETED) + { + rRenderContext.SetLineColor(mrSidebarWin.GetChangeColor()); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(GetPosPixel()), + rRenderContext.PixelToLogic(GetPosPixel() + Point(GetSizePixel().Width(), + GetSizePixel().Height()))); + rRenderContext.DrawLine(rRenderContext.PixelToLogic(GetPosPixel() + Point(GetSizePixel().Width(), + 0)), + rRenderContext.PixelToLogic(GetPosPixel() + Point(0, + GetSizePixel().Height()))); + } +} + +void SidebarTextControl::LogicInvalidate(const tools::Rectangle* pRectangle) +{ + tools::Rectangle aRectangle; + + if (!pRectangle) + { + Push(PushFlags::MAPMODE); + EnableMapMode(); + aRectangle = tools::Rectangle(Point(0, 0), PixelToLogic(GetSizePixel())); + Pop(); + } + else + aRectangle = *pRectangle; + + // Convert from relative twips to absolute ones. + vcl::Window& rParent = mrSidebarWin.EditWin(); + Point aOffset(GetOutOffXPixel() - rParent.GetOutOffXPixel(), GetOutOffYPixel() - rParent.GetOutOffYPixel()); + rParent.Push(PushFlags::MAPMODE); + rParent.EnableMapMode(); + aOffset = rParent.PixelToLogic(aOffset); + rParent.Pop(); + aRectangle.Move(aOffset.getX(), aOffset.getY()); + + OString sRectangle = aRectangle.toString(); + SwWrtShell& rWrtShell = mrDocView.GetWrtShell(); + SfxLokHelper::notifyInvalidation(rWrtShell.GetSfxViewShell(), sRectangle); +} + +void SidebarTextControl::KeyInput( const KeyEvent& rKeyEvt ) +{ + if (getenv("SW_DEBUG") && rKeyEvt.GetKeyCode().GetCode() == KEY_F12) + { + if (rKeyEvt.GetKeyCode().IsShift()) + { + mrDocView.GetDocShell()->GetDoc()->dumpAsXml(); + return; + } + } + + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + sal_uInt16 nKey = rKeyCode.GetCode(); + if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) && + ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) ) + { + mrSidebarWin.SwitchToPostIt(nKey); + } + else if ( nKey == KEY_ESCAPE || + ( rKeyCode.IsMod1() && + ( nKey == KEY_PAGEUP || + nKey == KEY_PAGEDOWN ) ) ) + { + mrSidebarWin.SwitchToFieldPos(); + } + else if ( rKeyCode.GetFullCode() == KEY_INSERT ) + { + mrSidebarWin.ToggleInsMode(); + } + else + { + // MakeVisible can lose our MapMode, save it. + auto oldMapMode = GetMapMode(); + //let's make sure we see our note + mrPostItMgr.MakeVisible(&mrSidebarWin); + if (comphelper::LibreOfficeKit::isActive()) + SetMapMode(oldMapMode); + + long aOldHeight = mrSidebarWin.GetPostItTextHeight(); + bool bDone = false; + + /// HACK: need to switch off processing of Undo/Redo in Outliner + if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) ) + { + bool bIsProtected = mrSidebarWin.IsProtected(); + if ( !bIsProtected || !EditEngine::DoesKeyChangeText(rKeyEvt) ) + { + bDone = GetTextView() && GetTextView()->PostKeyEvent( rKeyEvt ); + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr xQuery(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xQuery->run(); + } + } + if (bDone) + mrSidebarWin.ResizeIfNecessary( aOldHeight, mrSidebarWin.GetPostItTextHeight() ); + else + { + // write back data first when showing navigator + if ( nKey==KEY_F5 ) + mrSidebarWin.UpdateData(); + if (!mrDocView.KeyInput(rKeyEvt)) + Window::KeyInput(rKeyEvt); + } + } + + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTextControl::MouseMove( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + OutlinerView* pOutlinerView( GetTextView() ); + pOutlinerView->MouseMove( rMEvt ); + // mba: why does OutlinerView not handle the modifier setting?! + // this forces the postit to handle *all* pointer types + SetPointer( pOutlinerView->GetPointer( rMEvt.GetPosPixel() ) ); + + const EditView& aEV = pOutlinerView->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast( pField ); + if ( pURL ) + { + OUString sText(SfxHelp::GetURLHelpText(pURL->GetURL())); + Help::ShowQuickHelp( + this, PixelToLogic(tools::Rectangle(GetPosPixel(), Size(50, 10))), sText); + } + } + } +} + +void SidebarTextControl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + SvtSecurityOptions aSecOpts; + bool bExecuteMod = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink); + + if ( !bExecuteMod || (rMEvt.GetModifier() == KEY_MOD1)) + { + const EditView& aEV = GetTextView()->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pField = pItem->GetField(); + const SvxURLField* pURL = dynamic_cast( pField ); + if ( pURL ) + { + GetTextView()->MouseButtonDown( rMEvt ); + SwWrtShell &rSh = mrDocView.GetWrtShell(); + const OUString& sURL( pURL->GetURL() ); + const OUString& sTarget( pURL->GetTargetFrame() ); + ::LoadURL(rSh, sURL, LoadUrlFlags::NONE, sTarget); + return; + } + } + } + } + + GrabFocus(); + if ( GetTextView() ) + { + GetTextView()->MouseButtonDown( rMEvt ); + } + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTextControl::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + GetTextView()->MouseButtonUp( rMEvt ); +} + +IMPL_LINK( SidebarTextControl, OnlineSpellCallback, SpellCallbackInfo&, rInfo, void ) +{ + if ( rInfo.nCommand == SpellCallbackCommand::STARTSPELLDLG ) + { + mrDocView.GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SfxCallMode::ASYNCHRON); + } +} + +void SidebarTextControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) + { + if ( !mrSidebarWin.IsProtected() && + GetTextView() && + GetTextView()->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true )) + { + Link aLink = LINK(this, SidebarTextControl, OnlineSpellCallback); + GetTextView()->ExecuteSpellPopup(rCEvt.GetMousePosPixel(),&aLink); + } + else + { + Point aPos; + if (rCEvt.IsMouseEvent()) + aPos = rCEvt.GetMousePosPixel(); + else + { + const Size aSize = GetSizePixel(); + aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); + } + SfxDispatcher::ExecutePopup(this, &aPos); + } + } + else + if (rCEvt.GetCommand() == CommandEventId::Wheel) + { + if (mrSidebarWin.IsScrollbarVisible()) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if (pData->IsShift() || pData->IsMod1() || pData->IsMod2()) + { + mrDocView.HandleWheelCommands(rCEvt); + } + else + { + HandleScrollCommand( rCEvt, nullptr , mrSidebarWin.Scrollbar()); + } + } + else + { + mrDocView.HandleWheelCommands(rCEvt); + } + } + else + { + if ( GetTextView() ) + GetTextView()->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +OUString SidebarTextControl::GetSurroundingText() const +{ + if (GetTextView()) + return GetTextView()->GetSurroundingText(); + return OUString(); +} + +Selection SidebarTextControl::GetSurroundingTextSelection() const +{ + if( GetTextView() ) + return GetTextView()->GetSurroundingTextSelection(); + else + return Selection( 0, 0 ); +} + +css::uno::Reference< css::accessibility::XAccessible > SidebarTextControl::CreateAccessible() +{ + + SidebarTextControlAccessible* pAcc( new SidebarTextControlAccessible( *this ) ); + css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc ); + SetWindowPeer( xWinPeer, pAcc ); + + css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY ); + return xAcc; +} + +} // 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 000000000..ab9c7604e --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.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_DOCVW_SIDEBARTXTCONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_SIDEBARTXTCONTROL_HXX + +#include + +class OutlinerView; +class SwView; +class SwPostItMgr; +struct SpellCallbackInfo; +namespace sw::annotation { class SwAnnotationWin; } + +namespace sw::sidebarwindows { + +class SidebarTextControl : public Control +{ + private: + sw::annotation::SwAnnotationWin& mrSidebarWin; + SwView& mrDocView; + SwPostItMgr& mrPostItMgr; + + protected: + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + /// @see Window::LogicInvalidate(). + void LogicInvalidate(const tools::Rectangle* pRectangle) override; + virtual void Command( const CommandEvent& rCEvt ) override; + virtual void LoseFocus() override; + virtual void RequestHelp(const HelpEvent &rEvt) override; + virtual OUString GetSurroundingText() const override; + virtual Selection GetSurroundingTextSelection() const override; + + public: + SidebarTextControl( sw::annotation::SwAnnotationWin& rSidebarWin, + WinBits nBits, + SwView& rDocView, + SwPostItMgr& rPostItMgr ); + virtual ~SidebarTextControl() override; + virtual void dispose() override; + + virtual void GetFocus() override; + virtual void KeyInput( const KeyEvent& rKeyEvt ) override; + virtual void MouseButtonDown(const MouseEvent& rMouseEvent) override; + virtual void MouseButtonUp(const MouseEvent& rMEvt) override; + virtual void MouseMove(const MouseEvent& rMEvt) override; + + OutlinerView* GetTextView() const; + + DECL_LINK( OnlineSpellCallback, SpellCallbackInfo&, void ); + + virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override; + + virtual void Draw(OutputDevice* pDev, const Point&, DrawFlags) override; +}; + +} // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx b/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx new file mode 100644 index 000000000..d3bec6eca --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include "SidebarTxtControlAcc.hxx" + +#include "SidebarTxtControl.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sw::sidebarwindows { + +namespace { + +// declaration and implementation of +// for <::accessibility::AccessibleTextHelper> instance +class SidebarTextEditSource : public SvxEditSource, + public SfxBroadcaster +{ + public: + explicit SidebarTextEditSource(SidebarTextControl& rSidebarTextControl); + virtual ~SidebarTextEditSource() override; + + virtual std::unique_ptr Clone() const override; + + virtual SvxTextForwarder* GetTextForwarder() override; + virtual SvxViewForwarder* GetViewForwarder() override; + virtual SvxEditViewForwarder* GetEditViewForwarder( bool bCreate = false ) override; + + virtual void UpdateData() override; + + virtual SfxBroadcaster& GetBroadcaster() const override; + DECL_LINK( NotifyHdl, EENotify&, void ); + + private: + SidebarTextControl& mrSidebarTextControl; + SvxOutlinerForwarder mTextForwarder; + SvxDrawOutlinerViewForwarder mViewForwarder; +}; + +} + +SidebarTextEditSource::SidebarTextEditSource( SidebarTextControl& rSidebarTextControl ) + : SvxEditSource() + , mrSidebarTextControl( rSidebarTextControl ) + , mTextForwarder( *(rSidebarTextControl.GetTextView()->GetOutliner()), false ) + , mViewForwarder( *(rSidebarTextControl.GetTextView()) ) +{ + if ( mrSidebarTextControl.GetTextView() ) + { + mrSidebarTextControl.GetTextView()->GetOutliner()->SetNotifyHdl( LINK(this, SidebarTextEditSource, NotifyHdl) ); + } +} + +SidebarTextEditSource::~SidebarTextEditSource() +{ + if ( mrSidebarTextControl.GetTextView() ) + { + mrSidebarTextControl.GetTextView()->GetOutliner()->SetNotifyHdl( Link() ); + } +} + +std::unique_ptr SidebarTextEditSource::Clone() const +{ + return std::unique_ptr(new SidebarTextEditSource( mrSidebarTextControl )); +} + +SvxTextForwarder* SidebarTextEditSource::GetTextForwarder() +{ + return &mTextForwarder; +} + +SvxViewForwarder* SidebarTextEditSource::GetViewForwarder() +{ + return &mViewForwarder; +} + +SvxEditViewForwarder* SidebarTextEditSource::GetEditViewForwarder( bool /*bCreate*/ ) +{ + return &mViewForwarder; +} + +void SidebarTextEditSource::UpdateData() +{ + // nothing to do +} + +SfxBroadcaster& SidebarTextEditSource::GetBroadcaster() const +{ + return * const_cast< SidebarTextEditSource* > (this); +} + +IMPL_LINK(SidebarTextEditSource, NotifyHdl, EENotify&, rNotify, void) +{ + std::unique_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( &rNotify ) ); + + if (aHint) + { + Broadcast(*aHint); + } +} + +namespace { + +// declaration and implementation of accessible context for instance +class SidebarTextControlAccessibleContext : public VCLXAccessibleComponent +{ + public: + explicit SidebarTextControlAccessibleContext( SidebarTextControl& rSidebarTextControl ); + + virtual sal_Int32 SAL_CALL + getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleChild( sal_Int32 i ) override; + + virtual void SAL_CALL + addAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) override; + virtual void SAL_CALL + removeAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) override; + + protected: + virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override; + + private: + std::unique_ptr<::accessibility::AccessibleTextHelper> mpAccessibleTextHelper; + + ::osl::Mutex maMutex; +}; + +} + +SidebarTextControlAccessibleContext::SidebarTextControlAccessibleContext( SidebarTextControl& rSidebarTextControl ) + : VCLXAccessibleComponent( rSidebarTextControl.GetWindowPeer() ) + , maMutex() +{ + mpAccessibleTextHelper.reset(new ::accessibility::AccessibleTextHelper( std::make_unique(rSidebarTextControl) )); + mpAccessibleTextHelper->SetEventSource( rSidebarTextControl.GetWindowPeer() ); +} + +sal_Int32 SAL_CALL SidebarTextControlAccessibleContext::getAccessibleChildCount() +{ + osl::MutexGuard aGuard( maMutex ); + + sal_Int32 nChildCount( 0 ); + + if ( mpAccessibleTextHelper ) + { + nChildCount = mpAccessibleTextHelper->GetChildCount(); + } + + return nChildCount; +} + +css::uno::Reference< css::accessibility::XAccessible > SAL_CALL SidebarTextControlAccessibleContext::getAccessibleChild( sal_Int32 i ) +{ + osl::MutexGuard aGuard( maMutex ); + + css::uno::Reference< css::accessibility::XAccessible > xChild; + + if ( mpAccessibleTextHelper ) + { + xChild = mpAccessibleTextHelper->GetChild( i ); + } + + return xChild; +} + +void SAL_CALL SidebarTextControlAccessibleContext::addAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) +{ + osl::MutexGuard aGuard( maMutex ); + + if ( mpAccessibleTextHelper ) + { + mpAccessibleTextHelper->AddEventListener(xListener); + } +} + +void SAL_CALL SidebarTextControlAccessibleContext::removeAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) +{ + osl::MutexGuard aGuard( maMutex ); + + if ( mpAccessibleTextHelper ) + { + mpAccessibleTextHelper->RemoveEventListener(xListener); + } +} + +void SidebarTextControlAccessibleContext::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) +{ + if ( mpAccessibleTextHelper ) + { + switch ( rVclWindowEvent.GetId() ) + { + case VclEventId::ObjectDying: + { + mpAccessibleTextHelper.reset(); + } + break; + case VclEventId::WindowGetFocus: + case VclEventId::ControlGetFocus: + { + mpAccessibleTextHelper->SetFocus(); + } + break; + case VclEventId::WindowLoseFocus: + case VclEventId::ControlLoseFocus: + { + mpAccessibleTextHelper->SetFocus( false ); + } + break; + default: break; + } + } + + VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); +} + +// implementation of accessible for instance +SidebarTextControlAccessible::SidebarTextControlAccessible( SidebarTextControl& rSidebarTextControl ) + : VCLXWindow() + , mrSidebarTextControl( rSidebarTextControl ) +{ + SetWindow( &mrSidebarTextControl ); +} + +SidebarTextControlAccessible::~SidebarTextControlAccessible() +{ +} + +css::uno::Reference< css::accessibility::XAccessibleContext > SidebarTextControlAccessible::CreateAccessibleContext() +{ + SidebarTextControlAccessibleContext* pAccContext( + new SidebarTextControlAccessibleContext( mrSidebarTextControl ) ); + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc( pAccContext ); + return xAcc; +} + +} // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControlAcc.hxx b/sw/source/uibase/docvw/SidebarTxtControlAcc.hxx new file mode 100644 index 000000000..b05693484 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControlAcc.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_DOCVW_SIDEBARTXTCONTROLACC_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_SIDEBARTXTCONTROLACC_HXX + +#include + +namespace sw::sidebarwindows { + +class SidebarTextControl; + +class SidebarTextControlAccessible : public VCLXWindow +{ + public: + explicit SidebarTextControlAccessible( SidebarTextControl& rSidebarTextControl ); + virtual ~SidebarTextControlAccessible() override; + + virtual css::uno::Reference< css::accessibility::XAccessibleContext > + CreateAccessibleContext() override; + + private: + SidebarTextControl& mrSidebarTextControl; +}; + +} // end of namespace sw::sidebarwindows + +#endif + +/* 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 000000000..010394dad --- /dev/null +++ b/sw/source/uibase/docvw/SidebarWinAcc.cxx @@ -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 . + */ + +#include "SidebarWinAcc.hxx" +#include + +#include +#include +#include + +#include + +namespace sw::sidebarwindows { + +namespace { + +// declaration and implementation of accessible context for instance +class SidebarWinAccessibleContext : public VCLXAccessibleComponent +{ + public: + explicit SidebarWinAccessibleContext( sw::annotation::SwAnnotationWin& rSidebarWin, + SwViewShell& rViewShell, + const SwFrame* pAnchorFrame ) + : VCLXAccessibleComponent( rSidebarWin.GetWindowPeer() ) + , mrViewShell( rViewShell ) + , mpAnchorFrame( pAnchorFrame ) + , maMutex() + { + rSidebarWin.SetAccessibleRole( css::accessibility::AccessibleRole::COMMENT ); + } + + void ChangeAnchor( const SwFrame* pAnchorFrame ) + { + osl::MutexGuard aGuard(maMutex); + + mpAnchorFrame = pAnchorFrame; + } + + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleParent() override + { + osl::MutexGuard aGuard(maMutex); + + css::uno::Reference< css::accessibility::XAccessible > xAccParent; + + if ( mpAnchorFrame && + mrViewShell.GetAccessibleMap() ) + { + xAccParent = mrViewShell.GetAccessibleMap()->GetContext( mpAnchorFrame, false ); + } + + return xAccParent; + } + + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override + { + osl::MutexGuard aGuard(maMutex); + + sal_Int32 nIndex( -1 ); + + if ( mpAnchorFrame && GetWindow() && + mrViewShell.GetAccessibleMap() ) + { + nIndex = mrViewShell.GetAccessibleMap()->GetChildIndex( *mpAnchorFrame, + *GetWindow() ); + } + + return nIndex; + } + + private: + SwViewShell& mrViewShell; + const SwFrame* mpAnchorFrame; + + ::osl::Mutex maMutex; +}; + +} + +// implementation of accessible for instance +SidebarWinAccessible::SidebarWinAccessible( sw::annotation::SwAnnotationWin& rSidebarWin, + SwViewShell& rViewShell, + const SwSidebarItem& rSidebarItem ) + : VCLXWindow() + , mrSidebarWin( rSidebarWin ) + , mrViewShell( rViewShell ) + , mpAnchorFrame( rSidebarItem.maLayoutInfo.mpAnchorFrame ) + , bAccContextCreated( false ) +{ + SetWindow( &mrSidebarWin ); +} + +SidebarWinAccessible::~SidebarWinAccessible() +{ +} + +void SidebarWinAccessible::ChangeSidebarItem( const SwSidebarItem& rSidebarItem ) +{ + if ( bAccContextCreated ) + { + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc + = getAccessibleContext(); + if ( xAcc.is() ) + { + SidebarWinAccessibleContext* pAccContext = + dynamic_cast(xAcc.get()); + if ( pAccContext ) + { + pAccContext->ChangeAnchor( rSidebarItem.maLayoutInfo.mpAnchorFrame ); + } + } + } +} + +css::uno::Reference< css::accessibility::XAccessibleContext > SidebarWinAccessible::CreateAccessibleContext() +{ + SidebarWinAccessibleContext* pAccContext = + new SidebarWinAccessibleContext( mrSidebarWin, + mrViewShell, + mpAnchorFrame ); + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc( pAccContext ); + bAccContextCreated = true; + return xAcc; +} + +} // 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 000000000..f22dfac3e --- /dev/null +++ b/sw/source/uibase/docvw/SidebarWinAcc.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_DOCVW_SIDEBARWINACC_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_SIDEBARWINACC_HXX + +#include + +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 bAccContextCreated; +}; + +} // end of namespace sw::sidebarwindows + +#endif + +/* 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 000000000..4f7bda656 --- /dev/null +++ b/sw/source/uibase/docvw/UnfloatTableButton.cxx @@ -0,0 +1,233 @@ +/* -*- 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEXT_PADDING 3 +#define BOX_DISTANCE 3 +#define BUTTON_WIDTH 12 + +UnfloatTableButton::UnfloatTableButton(SwEditWin* pEditWin, const SwFrame* pFrame) + : SwFrameMenuButtonBase(pEditWin, pFrame) + , m_sLabel(SwResId(STR_UNFLOAT_TABLE)) +{ +} + +UnfloatTableButton::~UnfloatTableButton() { disposeOnce(); } + +void UnfloatTableButton::SetOffset(Point aTopRightPixel) +{ + // Compute the text size and get the box position & size from it + tools::Rectangle aTextRect; + GetTextBoundRect(aTextRect, m_sLabel); + tools::Rectangle aTextPxRect = LogicToPixel(aTextRect); + FontMetric aFontMetric = GetFontMetric(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); +} + +void UnfloatTableButton::MouseButtonDown(const MouseEvent& /*rMEvt*/) +{ + assert(GetFrame()->IsFlyFrame()); + // const_cast is needed because of bad design of ISwFrameControl and derived classes + SwFlyFrame* pFlyFrame = const_cast(static_cast(GetFrame())); + + // Find the table inside the text frame + SwTabFrame* pTableFrame = nullptr; + SwFrame* pLower = pFlyFrame->GetLower(); + while (pLower) + { + if (pLower->IsTabFrame()) + { + pTableFrame = static_cast(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(pAnchoreFrame); + if (pTextFrame->GetTextNodeFirst() == nullptr) + return; + + SwNodeIndex aInsertPos((*pTextFrame->GetTextNodeFirst())); + + 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 auto xTable = SwXTextTable::CreateXTextTable(pTableFormat); + const css::uno::Reference xSet(xTable, css::uno::UNO_QUERY); + assert(xSet); + xSet->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 + SfxItemSet aSet(GetEditWin()->GetView().GetWrtShell().GetAttrPool(), + svl::Items{}); + 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()); + } + } + + // Move the table outside of the text frame + SwNodeRange aRange(*pTableNode, 0, *pTableNode->EndOfSectionNode(), 1); + rDoc.getIDocumentContentOperations().MoveNodeRange(aRange, aInsertPos, SwMoveFlags::DEFAULT); + + // Remove the floating table's frame + SwFlyFrameFormat* pFrameFormat = pFlyFrame->GetFormat(); + if (pFrameFormat) + { + rDoc.getIDocumentLayoutAccess().DelLayoutFormat(pFrameFormat); + } + + 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::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + SetMapMode(MapMode(MapUnit::MapPixel)); + drawinglayer::primitive2d::Primitive2DContainer aSeq; + const ::tools::Rectangle aRect( + ::tools::Rectangle(Point(0, 0), rRenderContext.PixelToLogic(GetSizePixel()))); + + // Create button + SwFrameButtonPainter::PaintButton(aSeq, aRect, true); + + // Create the text primitive + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + basegfx::B2DVector aFontSize; + drawinglayer::attribute::FontAttribute aFontAttr + = drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontSize, rRenderContext.GetFont(), false, false); + + FontMetric aFontMetric = rRenderContext.GetFontMetric(rRenderContext.GetFont()); + double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING; + double nTextOffsetX = std::abs(aRect.GetWidth() - rRenderContext.GetTextWidth(m_sLabel)) / 2.0; + Point aTextPos(nTextOffsetX, nTextOffsetY); + + basegfx::B2DHomMatrix aTextMatrix(basegfx::utils::createScaleTranslateB2DHomMatrix( + aFontSize.getX(), aFontSize.getY(), static_cast(aTextPos.X()), + static_cast(aTextPos.Y()))); + + aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector(), aFontAttr, + css::lang::Locale(), aLineColor))); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + std::unique_ptr pProcessor( + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(rRenderContext, + aNewViewInfos)); + + pProcessor->process(aSeq); +} + +void UnfloatTableButton::ShowAll(bool bShow) { Show(bShow); } + +bool UnfloatTableButton::Contains(const Point& rDocPt) const +{ + ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel()); + if (aRect.IsInside(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/edtdd.cxx b/sw/source/uibase/docvw/edtdd.cxx new file mode 100644 index 000000000..44728b9ba --- /dev/null +++ b/sw/source/uibase/docvw/edtdd.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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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()) + { + bool bStart = false, bDelSelect = false; + SdrObject *pObj = nullptr; + Point aDocPos( PixelToLogic( rPosPixel ) ); + if ( !rSh.IsInSelect() && 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(); + if( rSh.SelectObj( aDocPos, 0, pObj )) + bStart = bDelSelect = true; + else + rSh.UnlockPaint(); + } + else + { + SwContentAtPos aSwContentAtPos( IsAttrAtPos::InetAttr ); + bStart = rSh.GetContentAtPos( aDocPos, + aSwContentAtPos ); + } + + if ( bStart && !m_bIsInDrag ) + { + m_bMBPressed = false; + ReleaseMouse(); + g_bFrameDrag = false; + g_bExecuteDrag = true; + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_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 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.IsInside(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.TestCurrPam( aDocPt ) + || 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.IsInside( 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 ( !bool(nDropDestination) ) + { + 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.IsInside(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( !bool(m_nDropDestination) ) + 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(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; + + if ( m_rView.GetViewFrame() ) + { + 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 000000000..507919f60 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -0,0 +1,6429 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "romenu.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +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; +static bool g_bModePushed = false; +bool g_bDDTimerStarted = false; +bool g_bFlushCharBuffer = false; +bool g_bDDINetAttr = false; +static SdrHdlKind g_eSdrMoveHdl = SdrHdlKind::User; + +QuickHelpData* SwEditWin::m_pQuickHlpData = nullptr; + +long SwEditWin::m_nDDStartPosY = 0; +long SwEditWin::m_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* pHdl; + Point aHdlPos; + Point aLastPos; + bool bTopRightHandle; +public: + explicit SwAnchorMarker( SdrHdl* pH ) + : pHdl( pH ) + , aHdlPos( pH->GetPos() ) + , aLastPos( pH->GetPos() ) + , bTopRightHandle( pH->GetKind() == SdrHdlKind::Anchor_TR ) + {} + const Point& GetLastPos() const { return aLastPos; } + void SetLastPos( const Point& rNew ) { aLastPos = rNew; } + void SetPos( const Point& rNew ) { pHdl->SetPos( rNew ); } + const Point& GetHdlPos() const { return aHdlPos; } + SdrHdl* GetHdl() const { return pHdl; } + void ChgHdl( SdrHdl* pNew ) + { + pHdl = pNew; + if ( pHdl ) + { + bTopRightHandle = (pHdl->GetKind() == SdrHdlKind::Anchor_TR); + } + } + Point GetPosForHitTest( const OutputDevice& rOut ) + { + Point aHitTestPos( pHdl->GetPos() ); + aHitTestPos = rOut.LogicToPixel( aHitTestPos ); + if ( 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> m_aHelpStrings; + /// Index of the current help string. + sal_uInt16 nCurArrPos; + static constexpr sal_uInt16 nNoPos = std::numeric_limits::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 ) +{ + 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( 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; + + SET_CURR_SHELL(&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 ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.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; + } + } + } + } + + // 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; + } + + 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().IsInside( 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 long coMinLen = 100; +#else + const long coMinLen = 50; +#endif + 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( OBJ_NONE, false ); + m_bInsFrame = true; + m_nInsFrameColCount = nCols; +} + +void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect ) +{ + SetSdrDrawMode( eSdrObjectKind ); + + if (bObjSelect) + m_rView.SetDrawFuncPtr(std::make_unique( &m_rView.GetWrtShell(), this, &m_rView )); + else + m_rView.SetDrawFuncPtr(std::make_unique( &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 ) +{ + const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); + if ( !rCTLOptions.IsCTLFontEnabled() || + !rCTLOptions.IsCTLSequenceChecking() ) + return false; + + if ( 0 == rCursor.Start()->nContent.GetIndex() ) /* first char needs not to be checked */ + return false; + + SwBreakIt *pBreakIter = SwBreakIt::Get(); + uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter(); + assert(xBI.is()); + 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(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_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()->nContent = 0; + + const OUString aOldText( rSh.GetCursor()->GetText() ); + const sal_Int32 nOldLen = aOldText.getLength(); + + SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); + + sal_Int32 nExpandSelection = 0; + if (nOldLen > 0) + { + sal_Int32 nTmpPos = nOldLen; + sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ? + i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; + + OUString aNewText( aOldText ); + if (rCTLOptions.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()->nContent.GetIndex(); + OSL_ENSURE( nCursorStartPos >= nExpandSelection, "cannot expand selection as specified!!" ); + if (nExpandSelection && nCursorStartPos >= nExpandSelection) + { + if (!rCursor.HasMark()) + rCursor.SetMark(); + rCursor.Start()->nContent -= 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(); + g_bFlushCharBuffer = false; + +} + +#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; + + SfxItemSet aSet( + rSh.GetAttrPool(), + svl::Items< + 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>{}); + 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(aSnap.Width()) / nDiv ) ); + nDiv = rSh.GetViewOptions()->GetDivisionY(); + if ( nDiv > 0 ) + aSnap.setHeight( std::max( sal_uLong(1), static_cast(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 SwPosition* pToCharContentPos = aSet.Get(RES_ANCHOR).GetContentAnchor(); + rSh.CalcBoundRect( aBoundRect, eAnchorId, + text::RelOrientation::FRAME, aVert.GetRelationOrient(), + pToCharContentPos, bFollowTextFlow, + false, &aRefPoint ); + } + long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() ); + long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() ); + long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() ); + 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 )) + { + 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(); + + long nX = 0; + 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(aSnap.Width()) / nDiv ) ); + nDiv = rSh.GetViewOptions()->GetDivisionY(); + if ( nDiv > 0 ) + aSnap.setHeight( std::max( sal_uLong(1), static_cast(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(rDragStat).SetNoSnap(); + if(bWasSnapEnabled) + pSdrView->SetSnapEnabled(false); + + pSdrView->MovAction(aEndPoint); + pSdrView->EndDragObj(); + rSh.SetModified(); + + // restore snap + if(!bWasNoSnap) + const_cast(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; + } + } + + if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && + m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard ) + { + m_pApplyTempl->m_pFormatClipboard->Erase(); + SetApplyTemplate(SwApplyTemplate()); + m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH); + } + else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && + 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(); + 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( m_pQuickHlpData->m_bIsDisplayed ) + { + aTmpQHD.Move( *m_pQuickHlpData ); + m_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 = m_pQuickHlpData->m_bAppendSpace; + m_pQuickHlpData->m_bAppendSpace = false; + + if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 ) + { + if( rKEvt.GetKeyCode().IsShift()) + { + GetView().GetDocShell()->GetDoc()->dumpAsXml(); + return; + } + else + { + SwRootFrame* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout(); + pLayout->dumpAsXml( ); + return; + } + } + + KeyEvent aKeyEvent( rKEvt ); + // look for vertical mappings + if( !bIsDocReadOnly && !rSh.IsSelFrameMode() && !rSh.IsObjSelected() ) + { + // must changed from switch to if, because the Linux + // compiler has problem with the code. Has to remove if the new general + // handler exist. + sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); + + 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; + } + + const SwFrameFormat* pFlyFormat = rSh.GetFlyFrameFormat(); + 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->Put32( xVar.get(), 1 ); + + xVar = new SbxVariable; + if( SvMacroItemId::SwFrmKeyInputAlpha == nEvent ) + xVar->PutChar( aCh ); + else + xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() ); + xArgs->Put32( 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(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 OSL_DEBUG_LEVEL > 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // for switching cursor behaviour in ReadOnly regions + if( 0x7210 == rKeyCode.GetFullCode() ) + rSh.SetReadOnlyAvailable( !rSh.IsReadOnlyAvailable() ); + else +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#endif + + 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: + 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; + 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) + { + 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()) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xInfo->run(); + eKeyState = SwKeyState::End; + } + break; + + case KEY_RETURN: + { + if ( !rSh.HasReadonlySel() + && !rSh.CursorInsideInputField() ) + { + 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 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 . + // Otherwise method + // should only change the state of + // the current paragraph depending of the key. + // On it is set to , + // on it is set to . + // Thus, assure that method + // 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()) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xInfo->run(); + eKeyState = SwKeyState::End; + } + break; + + case KEY_RIGHT: + { + eFlyState = SwKeyState::Fly_Change; + nDir = MOVE_RIGHT_BIG; + goto KEYINPUT_CHECKTABLE_INSDEL; + } + case KEY_TAB: + { + + if (rSh.IsFormProtected() || 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 ( !rSh.IsMultiSelection() + && rSh.IsFirstOfNumRuleAtCursorPos() + && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) + eKeyState = SwKeyState::NumIndentInc; + else + eKeyState = SwKeyState::NumDown; + } + else if ( rSh.GetTableFormat() ) + { + if( rSh.HasSelection() || rSh.HasReadonlySel() ) + eKeyState = SwKeyState::NextCell; + else + { + eKeyState = SwKeyState::CheckAutoCorrect; + eNextKeyState = SwKeyState::NextCell; + } + } + else if ( rSh.GetSelectionType() & + (SelectionType::Graphic | + SelectionType::Frame | + SelectionType::Ole | + SelectionType::DrawObject | + SelectionType::DbForm)) + + eKeyState = SwKeyState::NextObject; + 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: + { + if (rSh.IsFormProtected() || 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() ) + { + if ( !rSh.IsMultiSelection() + && rSh.IsFirstOfNumRuleAtCursorPos() + && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) + eKeyState = SwKeyState::NumIndentDec; + else + eKeyState = SwKeyState::NumUp; + } + else if ( rSh.GetTableFormat() ) + { + if( rSh.HasSelection() || rSh.HasReadonlySel() ) + eKeyState = SwKeyState::PrevCell; + else + { + eKeyState = SwKeyState::CheckAutoCorrect; + eNextKeyState = SwKeyState::PrevCell; + } + } + else if ( rSh.GetSelectionType() & + (SelectionType::Graphic | + SelectionType::Frame | + SelectionType::Ole | + SelectionType::DrawObject | + SelectionType::DbForm)) + + eKeyState = SwKeyState::PrevObject; + 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 + { + eKeyState = SwKeyState::InsTab; + } + } + 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; + } + } + 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 + { + SfxItemSet aSet(rSh.GetAttrPool(), svl::Items{}); + 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(rItem)); + } + } + } + break; + } + } + break; + + case SwKeyState::EnterCharCell: + { + eKeyState = SwKeyState::KeyToView; + switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() ) + { + case KEY_RIGHT | KEY_MOD2: + rSh.Right( CRSR_SKIP_CHARS, false, 1, false ); + eKeyState = SwKeyState::End; + FlushInBuffer(); + break; + case KEY_LEFT | KEY_MOD2: + rSh.Left( CRSR_SKIP_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)) + { + auto xInfo(std::make_shared(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog")); + weld::DialogController::runAsync(xInfo, [](int) {}); + 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 ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr ) + static_cast(m_rView.GetCurShell())->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 (dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr ) + static_cast(m_rView.GetCurShell())->Init(); + } + } + eKeyState = SwKeyState::End; + } + break; + case SwKeyState::EnterDrawHandleMode: + { + const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList(); + bool bForward(!aKeyEvent.GetKeyCode().IsShift()); + + const_cast(rHdlList).TravelFocusHdl(bForward); + eKeyState = SwKeyState::End; + } + break; + case SwKeyState::InsTab: + if( dynamic_cast( &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.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 ) && + '\"' != 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(); + g_bFlushCharBuffer = Application::AnyInput( VclInputFlags::KEYBOARD ); + bFlushBuffer = !g_bFlushCharBuffer; + if( g_bFlushCharBuffer ) + m_aKeyInputFlushTimer.Start(); + } + eKeyState = SwKeyState::End; + } + else + { + auto xInfo(std::make_shared(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog")); + weld::DialogController::runAsync(xInfo, [](int) {}); + eKeyState = SwKeyState::End; + } + break; + + case SwKeyState::CheckAutoCorrect: + { + if( pACorr && pACfg->IsAutoFormatByInput() && + pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord | + ACFlags::ChgOrdinalNumber | ACFlags::TransliterateRTL | + ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | + ACFlags::Autocorrect ) && + !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: + { + ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter(); + if(pFieldmark) rSh.GotoFieldmark(pFieldmark); + } + break; + + case SwKeyState::GotoPrevFieldMark: + { + ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore(); + if( pFieldmark ) + rSh.GotoFieldmark(pFieldmark); + } + 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); + m_pQuickHlpData->m_bAppendSpace = true; + } + } + else + { + sFnd = sFnd.copy(aTmpQHD.CurLen()); + rSh.Insert( sFnd ); + m_pQuickHlpData->m_bAppendSpace = !pACorr || + pACorr->GetSwFlags().bAutoCmpltAppendBlanc; + } + rSh.EndUndo( SwUndoId::END ); + } + break; + + case SwKeyState::NextPrevGlossary: + m_pQuickHlpData->Move( aTmpQHD ); + m_pQuickHlpData->Start(rSh, false); + break; + + case SwKeyState::EditFormula: + { + const sal_uInt16 nId = SwInputChild::GetChildWindowId(); + + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + pVFrame->ToggleChildWindow( nId ); + SwInputChild* pChildWin = static_cast(pVFrame-> + 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( &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 + sal_uInt16 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() ) + { + // bFlushCharBuffer was not reset here + // why not? + bool bSave = g_bFlushCharBuffer; + FlushInBuffer(); + g_bFlushCharBuffer = bSave; + + // 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(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); + if( pWrdCnt ) + pWrdCnt->UpdateCounts(); + +} + +/** + * MouseEvents + */ +void SwEditWin::RstMBDownFlags() +{ + // 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 && PopupMenu::IsInExecute() ) + return; + + MouseEvent rMEvt(_rMEvt); + + if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel())) + return; + + if (comphelper::LibreOfficeKit::isActive()) + { + if (vcl::Window* pWindow = m_rView.GetPostItMgr()->IsHitSidebarWindow(rMEvt.GetPosPixel())) + { + pWindow->MouseButtonDown(rMEvt); + return; + } + } + + m_rView.GetPostItMgr()->SetActiveSidebarWin(nullptr); + + GrabFocus(); + + //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() ); + } + + m_bWasShdwCursor = nullptr != m_pShadCursor; + m_pShadCursor.reset(); + + const Point aDocPos( PixelToLogic( rMEvt.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 ); + + // 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 ) + { + // When in Hide-Whitespace mode, we don't want header + // and footer controls. + if (!rSh.GetViewOptions()->IsHideWhitespaceMode()) + { + SwPaM aPam(*rSh.GetCurrentShellCursor().GetPoint()); + const bool bWasInHeader = aPam.GetPoint()->nNode.GetNode().FindHeaderStartNode() != nullptr; + const bool bWasInFooter = aPam.GetPoint()->nNode.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 + && rSh.GetViewOptions()->IsUseHeaderFooterMenu() && !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(); + + // Repaint everything + rSh.GetWin()->Invalidate(); + } + } + } + else + { + if ( rSh.IsHeaderFooterEdit( ) ) + rSh.ToggleHeaderFooterEdit( ); + else + { + // Make sure that the separators are hidden + rSh.SetShowHeaderFooterSeparator( FrameControlType::Header, false ); + rSh.SetShowHeaderFooterSeparator( FrameControlType::Footer, false ); + + // Repaint everything + // FIXME fdo#67358 for unknown reasons this causes painting + // problems when resizing table columns, so disable it +// rSh.GetWin()->Invalidate(); + } + + // 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(rSh.GetFlyFrameFormat()); + if ( rSh.Chainable( aDummy, *pFormat, aDocPos ) == SwChainRet::OK ) + rSh.Chain( *pFormat, aDocPos ); + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + return; + } + + // After GrabFocus a shell should be pushed. That should actually + // work but in practice ... + m_rView.SelectShellForDrop(); + + bool bCallBase = true; + + if( m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( rSh ); + m_pQuickHlpData->m_bAppendSpace = false; + + if( rSh.FinishOLEObj() ) + return; // end InPlace and the click doesn't count anymore + + SET_CURR_SHELL( &rSh ); + + SdrView *pSdrView = rSh.GetDrawView(); + if ( pSdrView ) + { + if (pSdrView->MouseButtonDown( rMEvt, this ) ) + { + rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); + return; // SdrView's event evaluated + } + } + + m_bIsInMove = false; + m_aStartPos = rMEvt.GetPosPixel(); + m_aRszMvHdlPt.setX( 0 ); + m_aRszMvHdlPt.setY( 0 ); + + SwTab nMouseTabCol = SwTab::COL_NONE; + const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() && + rMEvt.GetClicks() == 1 && MOUSE_LEFT == rMEvt.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( rMEvt, + (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( rMEvt, + 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 == rMEvt.GetButtons() ) + { + bool bOnlyText = false; + m_bMBPressed = true; + g_bNoInterrupt = true; + m_nKS_NUMDOWN_Count = 0; + + CaptureMouse(); + + // reset cursor position if applicable + rSh.ResetCursorStack(); + + switch ( rMEvt.GetModifier() + rMEvt.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, rMEvt.GetModifier() ); + return; + } + } + if ( EnterDrawMode( rMEvt, 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 (rMEvt.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) && + !(rMEvt.GetModifier() == KEY_SHIFT && !bHitHandle)) + { + rSh.EnterSelFrameMode( &aDocPos ); + if ( !m_pApplyTempl ) + { + // only if no position to size was hit. + if (!bHitHandle) + { + StartDDTimer(); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + } + g_bFrameDrag = true; + } + g_bNoInterrupt = false; + return; + } + } + } + } + + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::EOption::CtrlClickHyperlink ); + if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) || + ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) ) + bExecHyperlinks = true; + } + + // Enhanced selection + sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4); + if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() ) + nNumberOfClicks = 4; + + bool bExecDrawTextLink = false; + + switch ( rMEvt.GetModifier() + rMEvt.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, rMEvt.GetModifier() ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + + // hit a URL in DrawText object? + if (bExecHyperlinks && pSdrView) + { + SdrViewEvent aVEvt; + pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); + + if (aVEvt.eEvent == 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, + rMEvt.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, rMEvt.GetModifier() ); + } + return; + } + else + bOnlyText = rSh.IsObjSelectable( aDocPos ); + + if (!m_rView.GetDrawFuncPtr()) + rSh.ShowCursor(); + } + else + bOnlyText = KEY_MOD1 != rMEvt.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, rMEvt.GetModifier() ); + return; + } + else + { + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT :0; + if( rMEvt.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, rMEvt.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 ) ) + { + /* 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: + RstMBDownFlags(); + 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: + if (rSh.IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) + { + RstMBDownFlags(); + rSh.LaunchOLEObj(); + } + return; + + case SelectionType::Frame: + RstMBDownFlags(); + if (!comphelper::LibreOfficeKit::isActive()) + { + GetView().GetViewFrame()->GetBindings().Execute( + FN_FORMAT_FRAME_DLG, nullptr, + SfxCallMode::RECORD|SfxCallMode::SLOT); + } + return; + + case SelectionType::DrawObject: + RstMBDownFlags(); + EnterDrawTextMode(aDocPos); + if ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr ) + static_cast(m_rView.GetCurShell())->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() ) || + ( bFootnote = rSh.GetCurFootnote() ) ) ) + { + RstMBDownFlags(); + if( bFootnote ) + GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE ); + else + { + SwFieldTypesEnum nTypeId = pField->GetTypeId(); + SfxViewFrame* pVFrame = 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); + pVFrame->GetBindings().SetState(aItem); + pVFrame->GetBindings().Execute(nSlot); + break; + } + case SwFieldTypesEnum::Authority : + pVFrame->GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG); + break; + case SwFieldTypesEnum::Input: + case SwFieldTypesEnum::Dropdown: + case SwFieldTypesEnum::SetInput: + pVFrame->GetBindings().Execute(FN_UPDATE_INPUTFIELDS); + break; + default: + pVFrame->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 == rMEvt.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 ) + { + RstMBDownFlags(); + rSh.getIDocumentMarkAccess()->ClearFieldActivation(); + GetView().GetViewFrame()->GetBindings().Execute(SID_FM_CTL_PROPERTIES); + 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 == rMEvt.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 ( rMEvt.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::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_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 ( !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::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_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 ( !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::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + g_bFrameDrag = true; + return; + } + } + } + else + { + if ( rSh.IsSelFrameMode() && + rSh.IsInsideSelectedObj( aDocPos ) ) + { + rSh.EnterSelFrameMode( &aDocPos ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_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()->nContent + .GetIndex() != pTextField->GetStart()) + { + assert(rSh.GetCurrentShellCursor().GetPoint()->nContent + .GetIndex() == (pTextField->GetStart() + 1)); + rSh.Left( CRSR_SKIP_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 ) + { + 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.SelectText( 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 == rMEvt.GetButtons() && !rMEvt.GetModifier() + && static_cast< sal_uInt8 >(rMEvt.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.SelectText( aFieldAtPos.pFndTextAttr->GetStart() + 1, + *(aFieldAtPos.pFndTextAttr->End()) - 1 ); + } + } + + if (bCallBase) + Window::MouseButtonDown(rMEvt); +} + +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( m_pShadCursor && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) ) + { + m_pShadCursor.reset(); + } + + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly(); + + SET_CURR_SHELL( &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,this) ) + { + SetPointer( PointerStyle::Text ); + return; // evaluate SdrView's event + } + + const Point aOldPt( rSh.VisArea().Pos() ); + const bool bInsWin = rSh.VisArea().IsInside( aDocPt ) || comphelper::LibreOfficeKit::isActive(); + + 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::m_nDDStartPosX, SwEditWin::m_nDDStartPosY ); + aDD = LogicToPixel( aDD ); + tools::Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 ); + if ( !aRect.IsInside( 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( &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 SfxStringItem aCell( SID_TABLE_CELL, OUString() ); + 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(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->Put32( xVar.get(), ++nPos ); + + if( SvMacroItemId::SwFrmResize == nEvent ) + { + xVar = new SbxVariable; + xVar->PutUShort( static_cast< sal_uInt16 >(g_eSdrMoveHdl) ); + xArgs->Put32( xVar.get(), ++nPos ); + } + + xVar = new SbxVariable; + xVar->PutLong( aDocPt.X() - aSttPt.X() ); + xArgs->Put32( xVar.get(), ++nPos ); + xVar = new SbxVariable; + xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); + xArgs->Put32( 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 + KEY_MOD1 == + rMEvt.GetModifier() + rMEvt.GetButtons() ) && + 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(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(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() && !GetConnectMetaFile() ) + { + SwRect aRect; + sal_Int16 eOrient; + SwFillMode eMode = rSh.GetViewOptions()->GetShdwCursorFillMode(); + if( rSh.GetShadowCursorPos( aDocPt, eMode, aRect, eOrient )) + { + if( !m_pShadCursor ) + m_pShadCursor.reset( new SwShadowCursor( *this, + SwViewOption::GetDirectCursorColor() ) ); + if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient ) + eOrient = text::HoriOrientation::LEFT; + m_pShadCursor->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(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(); + SET_CURR_SHELL( &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,this ) ) + { + 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( OBJ_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->Put32( xVar.get(), ++nPos ); + + if( SvMacroItemId::SwFrmResize == nEvent ) + { + xVar = new SbxVariable; + xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) ); + xArgs->Put32( xVar.get(), ++nPos ); + } + + xVar = new SbxVariable; + xVar->PutLong( aDocPt.X() - aSttPt.X() ); + xArgs->Put32( xVar.get(), ++nPos ); + xVar = new SbxVariable; + xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); + xArgs->Put32( xVar.get(), ++nPos ); + + xVar = new SbxVariable; + xVar->PutUShort( 1 ); + xArgs->Put32( xVar.get(), ++nPos ); + + ReleaseMouse(); + + rSh.ExecMacro( *pMacro, nullptr, xArgs.get() ); + + CaptureMouse(); + } + } + 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 ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.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); + + 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 ); + // 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 ( 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(*fieldBM); + rCheckboxFm.SetChecked(!rCheckboxFm.IsChecked()); + rCheckboxFm.Invalidate(); + rSh.InvalidateWindows( m_rView.GetVisArea() ); + } + } + } + else if ( IsAttrAtPos::InetAttr == aContentAtPos.eContentAtPos ) + { + if (comphelper::LibreOfficeKit::isActive()) + { + OUString val((*static_cast(aContentAtPos.aFnd.pAttr)).GetValue()); + if (val.startsWith("#")) + bExecHyperlinks = true; + } + if ( bExecHyperlinks && aContentAtPos.aFnd.pAttr ) + rSh.ClickToINetAttr( *static_cast(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.eEvent == SdrEventKind::ExecuteUrl) + { + // hit URL field + const SvxURLField *pField = aVEvt.pURLField; + 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() && + !GetConnectMetaFile() && + rSh.VisArea().IsInside( 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; + bool bNoParagraphFormats = true; + { + 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 = false; + } + //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_COLOR_BACKGROUND_EXT: + 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, 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( 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(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()) + { + // 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 ( dynamic_cast< const SwDrawTextShell *>( m_rView.GetCurShell() ) != nullptr ) + static_cast(m_rView.GetCurShell())->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): + Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)), + DropTargetHelper( this ), + DragSourceHelper( this ), + + m_eBufferLanguage(LANGUAGE_DONTKNOW), + 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(OBJ_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( 200 ); + 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( m_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() ) + m_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::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_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(); + m_rView.GetWrtShell().InvalidateAccessibleFocus(); + } +} + +void SwEditWin::LoseFocus() +{ + if (m_rView.GetWrtShellPtr()) + m_rView.GetWrtShell().InvalidateAccessibleFocus(); + Window::LoseFocus(); + if( m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); +} + +void SwEditWin::Command( const CommandEvent& rCEvt ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + if ( !m_rView.GetViewFrame() ) + { + // If ViewFrame dies shortly, no popup anymore! + Window::Command(rCEvt); + return; + } + + // 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(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()) + { + SET_CURR_SHELL( &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(); + ScopedVclPtr pMenu; + if (GetView().TryContextMenuInterception(aROPopup.GetMenu(), "private:resource/ReadonlyContextMenu", pMenu, aEvent)) + { + if ( pMenu ) + { + sal_uInt16 nExecId = static_cast(pMenu.get())->Execute(this, aPixPos); + if( !::ExecuteMenuCommand( *static_cast(pMenu.get()), *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: + m_pShadCursor.reset(); + bCallBase = !m_rView.HandleWheelCommands( rCEvt ); + break; + + case CommandEventId::LongPress: + case CommandEventId::Swipe: //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) + { + if( m_pQuickHlpData->m_bIsDisplayed ) + m_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); + } + } + } + } + break; + case CommandEventId::CursorPos: + // will be handled by the base class + break; + + case CommandEventId::PasteSelection: + if( !m_rView.GetDocShell()->IsReadOnly() ) + { + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSelection( this )); + if( !aDataHelper.GetXTransferable().is() ) + break; + + SotExchangeDest nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() ); + if( !bool(nDropDestination) ) + 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 && SW_MOD()->GetCTLOptions().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()->nContent += sal::static_int_cast(pData->GetStart()); + rSh.SetMark(); + rSh.GetCursor()->GetMark()->nContent += sal::static_int_cast(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 ) + { + sal_uLong nPosNodeIdx = pCursor->GetPoint()->nNode.GetIndex(); + const sal_Int32 nPosIdx = pCursor->GetPoint()->nContent.GetIndex(); + sal_uLong nMarkNodeIdx = pCursor->GetMark()->nNode.GetIndex(); + const sal_Int32 nMarkIdx = pCursor->GetMark()->nContent.GetIndex(); + + if( !rSh.GetCursor()->HasMark() ) + rSh.GetCursor()->SetMark(); + + rSh.SttCursorMove(); + + if( nPosNodeIdx < nMarkNodeIdx ) + { + rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx; + rSh.GetCursor()->GetPoint()->nContent = nPosIdx; + rSh.GetCursor()->GetMark()->nNode = nPosNodeIdx; + rSh.GetCursor()->GetMark()->nContent = + rSh.GetCursor()->GetContentNode()->Len(); + } + else if( nPosNodeIdx == nMarkNodeIdx ) + { + rSh.GetCursor()->GetPoint()->nNode = nPosNodeIdx; + rSh.GetCursor()->GetPoint()->nContent = nPosIdx; + rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx; + rSh.GetCursor()->GetMark()->nContent = nMarkIdx; + } + else + { + rSh.GetCursor()->GetMark()->nNode = nMarkNodeIdx; + rSh.GetCursor()->GetMark()->nContent = nMarkIdx; + rSh.GetCursor()->GetPoint()->nNode = nMarkNodeIdx; + rSh.GetCursor()->GetPoint()->nContent = + rSh.GetCursor()->GetContentNode( false )->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.nNode.GetNode(), rPos.nContent.GetIndex() ); + if ( pInput ) + { + const SwPosition& rStart = *pInput->Start(); + const SwPosition& rEnd = *pInput->End(); + int nSize = 0; + for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) + { + ++nSize; + } + 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 aRects(new tools::Rectangle[ nSize ]); + int nRectIndex = 0; + for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) + { + const SwPosition aPos( rStart.nNode, 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 + 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, this ) ) + { + pSdrView->MouseButtonUp( aMEvt, this ); + 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() +{ + m_pQuickHlpData = new QuickHelpData(); +} + +void SwEditWin::FinitStaticData() +{ + delete m_pQuickHlpData; +} +/* i#3370 - remove quick help to prevent saving + * of autocorrection suggestions */ +void SwEditWin::StopQuickHelp() +{ + if( HasFocus() && m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed ) + m_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() +{ + 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; +} + +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 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, OUString(rWord[0]) ); + if ( rWord == sWordSentence ) + aWordCase = CASE_SENTENCE; + else + { + if ( rWord == rCC.uppercase( rWord ) ) + aWordCase = CASE_UPPER; + } + } + } + + salhelper::SingletonRef* pCalendar = s_getCalendarWrapper(); + (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() ); + + // Add matching calendar month and day names + for ( const auto& aNames : { (*pCalendar)->getMonths(), (*pCalendar)->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, OUString(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 strings; + + if ( rACList.GetWordsMatching( rWord, strings ) ) + { + 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, OUString(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& s1, + const std::pair& 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& s1, + const std::pair& 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& rChunkCandidates) +{ + m_pQuickHlpData->ClearContent(); + if (!rChunkCandidates.empty()) + { + SwGlossaryList* pList = ::GetGlossaryList(); + pList->HasLongName(rChunkCandidates, m_pQuickHlpData->m_aHelpStrings); + } + + if (!m_pQuickHlpData->m_aHelpStrings.empty()) + { + m_pQuickHlpData->Start(m_rView.GetWrtShell(), true); + } + return !m_pQuickHlpData->m_aHelpStrings.empty(); +} + +void SwEditWin::ShowAutoCorrectQuickHelp( + const OUString& rWord, SvxAutoCorrect& rACorr ) +{ + if (rWord.isEmpty()) + return; + SwWrtShell& rSh = m_rView.GetWrtShell(); + m_pQuickHlpData->ClearContent(); + + if( m_pQuickHlpData->m_aHelpStrings.empty() && + rACorr.GetSwFlags().bAutoCompleteWords ) + { + m_pQuickHlpData->m_bIsAutoText = false; + m_pQuickHlpData->m_bIsTip = rACorr.GetSwFlags().bAutoCmpltShowAsTip; + + // Get the necessary data to show help text. + m_pQuickHlpData->FillStrArr( rSh, rWord ); + } + + if( !m_pQuickHlpData->m_aHelpStrings.empty() ) + { + m_pQuickHlpData->SortAndFilter(rWord); + m_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()->nNode.GetNode().FindFlyStartNode(); + if ( pStartFly ) + { + bOverFly = true; + SwFrameFormat* pFlyFormat = pStartFly->GetFlyFormat( ); + if ( pFlyFormat ) + { + const SwPosition* pAnchor = pFlyFormat->GetAnchor( ).GetContentAnchor( ); + if ( pAnchor ) + { + bool bInHeader = pAnchor->nNode.GetNode( ).FindHeaderStartNode( ) != nullptr; + bool bInFooter = pAnchor->nNode.GetNode( ).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 +{ + OUString sReturn; + SwWrtShell& rSh = m_rView.GetWrtShell(); + if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() ) + rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); + else if( !rSh.HasSelection() ) + { + SwPosition *pPos = rSh.GetCursor()->GetPoint(); + const sal_Int32 nPos = pPos->nContent.GetIndex(); + + // get the sentence around the cursor + rSh.HideCursor(); + rSh.GoStartSentence(); + rSh.SetMark(); + rSh.GoEndSentence(); + rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); + + pPos->nContent = nPos; + rSh.ClearMark(); + rSh.HideCursor(); + } + + return sReturn; +} + +Selection SwEditWin::GetSurroundingTextSelection() const +{ + SwWrtShell& rSh = m_rView.GetWrtShell(); + if( rSh.HasSelection() ) + { + OUString sReturn; + rSh.GetSelectedText( sReturn, ParaBreakType::ToOnlyCR ); + return Selection( 0, sReturn.getLength() ); + } + else + { + // Return the position of the visible cursor in the sentence + // around the visible cursor. + SwPosition *pPos = rSh.GetCursor()->GetPoint(); + const sal_Int32 nPos = pPos->nContent.GetIndex(); + + rSh.HideCursor(); + rSh.GoStartSentence(); + const sal_Int32 nStartPos = rSh.GetCursor()->GetPoint()->nContent.GetIndex(); + + pPos->nContent = nPos; + rSh.ClearMark(); + rSh.ShowCursor(); + + return Selection( nPos - nStartPos, nPos - nStartPos ); + } +} + +void SwEditWin::LogicInvalidate(const tools::Rectangle* pRectangle) +{ + OString sRectangle; + if (!pRectangle) + sRectangle = "EMPTY"; + else + sRectangle = pRectangle->toString(); + + SfxLokHelper::notifyInvalidation(&m_rView, sRectangle); +} + +void SwEditWin::LogicMouseButtonDown(const MouseEvent& rMouseEvent) +{ + // When we're not doing tiled rendering, then positions must be passed as pixels. + assert(comphelper::LibreOfficeKit::isActive()); + + Point aPoint = GetPointerPosPixel(); + SetLastMousePos(rMouseEvent.GetPosPixel()); + + MouseButtonDown(rMouseEvent); + + SetPointerPosPixel(aPoint); +} + +void SwEditWin::LogicMouseButtonUp(const MouseEvent& rMouseEvent) +{ + // When we're not doing tiled rendering, then positions must be passed as pixels. + assert(comphelper::LibreOfficeKit::isActive()); + + Point aPoint = GetPointerPosPixel(); + SetLastMousePos(rMouseEvent.GetPosPixel()); + + MouseButtonUp(rMouseEvent); + + SetPointerPosPixel(aPoint); +} + +void SwEditWin::LogicMouseMove(const MouseEvent& rMouseEvent) +{ + // When we're not doing tiled rendering, then positions must be passed as pixels. + assert(comphelper::LibreOfficeKit::isActive()); + + Point aPoint = GetPointerPosPixel(); + SetLastMousePos(rMouseEvent.GetPosPixel()); + + MouseMove(rMouseEvent); + + SetPointerPosPixel(aPoint); +} + +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; +} + +/* 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 000000000..b48b18ec4 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin2.cxx @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon ) +{ + const char* pResId = nullptr; + switch( rRedl.GetType() ) + { + case RedlineType::Insert: pResId = STR_REDLINE_INSERT; break; + case RedlineType::Delete: pResId = 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; + } + + OUStringBuffer sBuf; + if (pResId) + { + sBuf.append(SwResId(pResId)); + sBuf.append(": "); + sBuf.append(rRedl.GetAuthorString()); + sBuf.append(" - "); + sBuf.append(GetAppLangDateTimeString(rRedl.GetTimeStamp())); + if( bBalloon && !rRedl.GetComment().isEmpty() ) + sBuf.append('\n').append(rRedl.GetComment()); + } + return sBuf.makeStringAndClear(); +} + +OUString SwEditWin::ClipLongToolTip(const OUString& rText) +{ + OUString sDisplayText(rText); + long nTextWidth = GetTextWidth(sDisplayText); + long nMaxWidth = GetDesktopRectPixel().GetWidth() * 2 / 3; + nMaxWidth = PixelToLogic(Size(nMaxWidth, 0)).Width(); + if (nTextWidth > nMaxWidth) + sDisplayText = GetEllipsisString(sDisplayText, nMaxWidth, DrawTextFlags::CenterEllipsis); + return sDisplayText; +} + +void SwEditWin::RequestHelp(const HelpEvent &rEvt) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + bool bQuickBalloon = bool(rEvt.GetMode() & ( HelpEventMode::QUICK | HelpEventMode::BALLOON )); + if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips()) + return; + bool bContinue = true; + SET_CURR_SHELL(&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(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 ); + + if( rSh.GetContentAtPos( aPos, aContentAtPos, false, &aFieldRect ) ) + { + QuickHelpFlags nStyle = QuickHelpFlags::NONE; // style of quick help + switch( aContentAtPos.eContentAtPos ) + { + case IsAttrAtPos::TableBoxFml: + sText = "= " + static_cast(aContentAtPos.aFnd.pAttr)->GetFormula(); + break; +#ifdef DBG_UTIL + case IsAttrAtPos::TableBoxValue: + { + sText = OStringToOUString(OString::number( + static_cast(aContentAtPos.aFnd.pAttr)->GetValue()), + osl_getThreadTextEncoding()); + break; + } + case IsAttrAtPos::CurrAttrs: + sText = aContentAtPos.sStr; + break; +#endif + + case IsAttrAtPos::InetAttr: + { + sText = static_cast(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() ) + { + OUString sSuffix( sText.copy(nFound) ); + if( sSuffix == "table" || + sSuffix == "frame" || + sSuffix == "region" || + sSuffix == "outline" || + sSuffix == "text" || + sSuffix == "graphic" || + sSuffix == "ole" ) + 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().nNode.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(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::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); + 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) + ": "; + sText += static_cast(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(pField)->SetSubType(nsSwExtendedSubType::SUB_CMD); + sText = pField->ExpandField(true, rSh.GetLayout()); + const_cast(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: + case SwFieldIds::HiddenText: + sText = pField->GetPar1(); + break; + + case SwFieldIds::DocStat: + break; + + case SwFieldIds::Macro: + sText = static_cast(pField)->GetMacro(); + break; + + case SwFieldIds::GetRef: + { + // #i85090# + const SwGetRefField* pRefField( dynamic_cast(pField) ); + OSL_ENSURE( pRefField, + " - unexpected type of " ); + if ( pRefField ) + { + if ( pRefField->IsRefToHeadingCrossRefBookmark() || + pRefField->IsRefToNumItemCrossRefBookmark() ) + { + sText = pRefField->GetExpandedTextOfReferencedTextNode(*rSh.GetLayout()); + if ( sText.getLength() > 80 ) + { + sText = sText.copy(0, 80) + "..."; + } + } + else + { + sText = static_cast(pField)->GetSetRefName(); + } + } + 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); + } + } + } + } + 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*/) +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + + if(pWrtShell) + { + pWrtShell->PrePaint(); + } +} + +void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + if(!pWrtShell) + return; + bool bPaintShadowCursor = false; + if( m_pShadCursor ) + { + tools::Rectangle aRect( m_pShadCursor->GetRect()); + // fully resides inside? + if( rRect.IsInside( aRect ) ) + { + // then cancel + m_pShadCursor.reset(); + } + else if( rRect.IsOver( aRect )) + { + // resides somewhat above, then everything is clipped outside + // and we have to make the "inner part" at the end of the + // Paint visible again. Otherwise Paint errors occur! + bPaintShadowCursor = true; + } + } + + if ( GetView().GetVisArea().GetWidth() <= 0 || + GetView().GetVisArea().GetHeight() <= 0 ) + Invalidate( rRect ); + else + { + pWrtShell->setOutputToWindow(true); + pWrtShell->Paint(rRenderContext, rRect); + pWrtShell->setOutputToWindow(false); + } + + if( bPaintShadowCursor ) + m_pShadCursor->Paint(); +} + +/* 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 000000000..583f485f3 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin3.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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(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(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(pSfxViewShell)) + pSwView->DocSzChgd(rSize); + else if (SwPagePreview* pSwPageView = dynamic_cast(pSfxViewShell)) + pSwPageView->DocSzChgd(rSize); +} + +// Notify for page number update +void PageNumNotify( SwViewShell const * pVwSh, sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, + const OUString& rPgStr) +{ + SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell(); + + if (SwView* pSwView = dynamic_cast(pSfxViewShell)) + { + if (pSwView->GetCurShell()) + pSwView->UpdatePageNums(nPhyNum, nVirtNum, rPgStr); + } +} + +void FrameNotify( SwViewShell* pVwSh, FlyMode eMode ) +{ + if (SwWrtShell* pWrtShell = dynamic_cast(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 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(pSfxViewShell)) + pSwPagePreview->RepaintCoreRect(rRect); +} + +bool JumpToSwMark( SwViewShell const * pVwSh, const OUString& rMark ) +{ + SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell(); + + if (SwView* pSwView = dynamic_cast(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(); + bUnlockPaint = true; + pSh->DeleteReplacementBitmaps(); + GetView().InvalidateBorder(); //Scrollbar work + } + break; + + case DataChangedEventType::PRINTER: + case DataChangedEventType::DISPLAY: + case DataChangedEventType::FONTS: + case DataChangedEventType::FONTSUBSTITUTION: + pSh->LockPaint(); + 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 000000000..17da0beee --- /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 +#include +#include +#include + +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 > 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 000000000..4e8d7b41a --- /dev/null +++ b/sw/source/uibase/docvw/frmsidebarwincontainer.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_DOCVW_FRMSIDEBARWINCONTAINER_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_FRMSIDEBARWINCONTAINER_HXX + +#include +#include +#include + +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 mpFrameSidebarWinContainer; +}; + +} // namespace sw::sidebarwindows + +#endif + +/* 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 000000000..75aa8847d --- /dev/null +++ b/sw/source/uibase/docvw/romenu.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "romenu.hxx" +#include +#include + +#include + +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 _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(_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, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/readonlymenu.ui", "") + , m_xMenu(m_aBuilder.get_menu("menu")) + , m_nReadonlyOpenurl(m_xMenu->GetItemId("openurl")) + , m_nReadonlyOpendoc(m_xMenu->GetItemId("opendoc")) + , m_nReadonlyEditdoc(m_xMenu->GetItemId("edit")) + , m_nReadonlySelectionMode(m_xMenu->GetItemId("selection")) + , m_nReadonlyReload(m_xMenu->GetItemId("reload")) + , m_nReadonlyReloadFrame(m_xMenu->GetItemId("reloadframe")) + , m_nReadonlySourceview(m_xMenu->GetItemId("html")) + , m_nReadonlyBrowseBackward(m_xMenu->GetItemId("backward")) + , m_nReadonlyBrowseForward(m_xMenu->GetItemId("forward")) + , m_nReadonlySaveGraphic(m_xMenu->GetItemId("savegraphic")) + , m_nReadonlyGraphictogallery(m_xMenu->GetItemId("graphictogallery")) + , m_nReadonlyTogallerylink(m_xMenu->GetItemId("graphicaslink")) + , m_nReadonlyTogallerycopy(m_xMenu->GetItemId("graphicascopy")) + , m_nReadonlySaveBackground(m_xMenu->GetItemId("savebackground")) + , m_nReadonlyBackgroundtogallery(m_xMenu->GetItemId("backgroundtogallery")) + , m_nReadonlyBackgroundTogallerylink(m_xMenu->GetItemId("backaslink")) + , m_nReadonlyBackgroundTogallerycopy(m_xMenu->GetItemId("backascopy")) + , m_nReadonlyCopylink(m_xMenu->GetItemId("copylink")) + , m_nReadonlyLoadGraphic(m_xMenu->GetItemId("loadgraphic")) + , m_nReadonlyGraphicoff(m_xMenu->GetItemId("imagesoff")) + , m_nReadonlyFullscreen(m_xMenu->GetItemId("fullscreen")) + , m_nReadonlyCopy(m_xMenu->GetItemId("copy")) + , m_rView(rV) + , m_xBrushItem(std::make_unique(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(aContentAtPos.aFnd.pAttr); + m_sURL = rIItem.GetValue(); + m_sTargetFrameName = rIItem.GetTargetFrame(); + } + } + + bool bLink = false; + const Graphic *pGrf; + if ( nullptr == (pGrf = rSh.GetGrfAtPos( rDPos, m_sGrfName, bLink )) ) + { + 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 * pVFrame = rV.GetViewFrame(); + SfxDispatcher &rDis = *pVFrame->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 pState; + + SfxItemState eState = pVFrame->GetBindings().QueryState( SID_COPY, pState ); + Check(m_nReadonlyCopy, SID_COPY, rDis); + if (eState < SfxItemState::DEFAULT) + m_xMenu->EnableItem(m_nReadonlyCopy, false); + + eState = pVFrame->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, 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 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 000000000..7d2e82994 --- /dev/null +++ b/sw/source/uibase/docvw/romenu.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_DOCVW_ROMENU_HXX +#define INCLUDED_SW_SOURCE_UIBASE_DOCVW_ROMENU_HXX + +#include +#include +#include +#include + +class SwView; +class SfxDispatcher; +class ImageMap; +class INetImage; + +class SwReadOnlyPopup +{ + VclBuilder m_aBuilder; + ScopedVclPtr 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 m_xBrushItem; + Graphic m_aGraphic; + OUString m_sURL, + m_sTargetFrameName; + OUString m_sGrfName; + std::vector 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); + PopupMenu& GetMenu() const { return *m_xMenu; } + ~SwReadOnlyPopup(); + + void Execute( vcl::Window* pWin, const Point &rPPos ); + void Execute( vcl::Window* pWin, sal_uInt16 nId ); +}; + +#endif + +/* 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 000000000..59d4e2555 --- /dev/null +++ b/sw/source/uibase/docvw/srcedtw.cxx @@ -0,0 +1,995 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +struct TextPortion +{ + sal_uInt16 nStart, nEnd; + svtools::ColorConfigEntry eType; +}; + +} + +#define MAX_SYNTAX_HIGHLIGHT 20 +#define MAX_HIGHLIGHTTIME 200 + +typedef std::vector TextPortions; + +static void lcl_Highlight(const OUString& rSource, 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_uInt16 nStrLen = rSource.getLength(); + sal_uInt16 nInsert = 0; // number of inserted portions + sal_uInt16 nActPos = 0; // position, where '<' was found + sal_uInt16 nPortStart = USHRT_MAX; // for the TextPortion + sal_uInt16 nPortEnd = 0; + TextPortion aText; + while(nActPos < nStrLen) + { + svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN; + if((nActPos < nStrLen - 2) && (rSource[nActPos] == cOpenBracket)) + { + // 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 = rSource[nActPos + 1]; + sal_Unicode cFollowNext = rSource[nActPos + 2]; + if(cExclamation == cFollowFirst) + { + // " nActPos + 1) + { + // some string was found + OUString sToken = rSource.copy(nActPos + 1, nSrchPos - nActPos - 1 ); + sToken = sToken.toAsciiUpperCase(); + HtmlTokenId nToken = ::GetHTMLToken(sToken); + if(nToken != HtmlTokenId::NONE) + { + // Token was found + eFoundType = svtools::HTMLKEYWORD; + nPortEnd = nSrchPos; + nPortStart = nActPos; + } + else + { + // what was that? + SAL_WARN( + "sw.level2", + "Token " << sToken + << " not recognised!"); + } + + } + } + // now we still have to look for '>' + if(svtools::HTMLUNKNOWN != eFoundType) + { + bool bFound = false; + for(sal_uInt16 i = nPortEnd; i < nStrLen; i++) + if(cCloseBracket == rSource[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): editor_(editor) {} + +private: + virtual ~ChangesListener() override {} + + virtual void SAL_CALL disposing(css::lang::EventObject const &) override + { + osl::MutexGuard g(editor_.mutex_); + editor_.m_xNotifier.clear(); + } + + virtual void SAL_CALL propertiesChange( + css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override + { + SolarMutexGuard g; + editor_.SetFont(); + } + + SwSrcEditWindow & 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); + { + osl::MutexGuard g(mutex_); + m_xNotifier = n; + } + css::uno::Sequence< OUString > s(2); + s[0] = "FontHeight"; + s[1] = "FontName"; + n->addPropertiesChangeListener(s, m_xListener.get()); +} + +SwSrcEditWindow::~SwSrcEditWindow() +{ + disposeOnce(); +} + +void SwSrcEditWindow::dispose() +{ + css::uno::Reference< css::beans::XMultiPropertySet > n; + { + osl::MutexGuard g(mutex_); + n = m_xNotifier; + } + if (n.is()) { + n->removePropertiesChangeListener(m_xListener.get()); + } + 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; + + long nVisY = m_pTextView->GetStartDocPos().Y(); + m_pTextView->ShowCursor(); + Size aOutSz( GetOutputSizePixel() ); + 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(); + } + 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( pTextView->GetTextEngine()->GetFont() ); + aFont.SetFillColor( rCol ); + pTextView->GetTextEngine()->SetFont( aFont ); + } + break; + default: break; + } +} + +void TextViewOutWin::MouseMove( const MouseEvent &rEvt ) +{ + if ( pTextView ) + pTextView->MouseMove( rEvt ); +} + +void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt ) +{ + if ( pTextView ) + { + pTextView->MouseButtonUp( rEvt ); + SfxViewFrame *pFrame = static_cast(GetParent())->GetSrcView()->GetViewFrame(); + if ( pFrame ) + { + SfxBindings& rBindings = pFrame->GetBindings(); + rBindings.Invalidate( SID_TABLE_CELL ); + rBindings.Invalidate( SID_CUT ); + rBindings.Invalidate( SID_COPY ); + } + } +} + +void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt ) +{ + GrabFocus(); + if ( pTextView ) + 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(GetParent())->HandleWheelCommand( rCEvt ); + } + } + break; + + default: + if ( pTextView ) + pTextView->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +void TextViewOutWin::KeyInput( const KeyEvent& rKEvt ) +{ + bool bDone = false; + SwSrcEditWindow* pSrcEditWin = static_cast(GetParent()); + bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt ); + if(bChange) + bDone = pTextView->KeyInput( rKEvt ); + + SfxBindings& rBindings = static_cast(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) +{ + pTextView->Paint(rRenderContext, rRect); +} + +void SwSrcEditWindow::CreateTextEngine() +{ + // FIXME RenderContext + + const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); + m_pOutWin = VclPtr::Create(this, 0); + m_pOutWin->SetBackground(Wallpaper(rCol)); + m_pOutWin->SetPointer(PointerStyle::Text); + m_pOutWin->Show(); + + // create Scrollbars + m_pHScrollbar = VclPtr::Create(this, WB_3DLOOK |WB_HSCROLL|WB_DRAG); + m_pHScrollbar->EnableRTL( false ); + m_pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + m_pHScrollbar->Show(); + + m_pVScrollbar = VclPtr::Create(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); + m_pVScrollbar->EnableRTL( false ); + m_pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + m_pHScrollbar->EnableDrag(); + 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(*this, 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(SwSrcEditWindow, ScrollHdl, ScrollBar*, pScroll, void) +{ + if(pScroll == m_pVScrollbar) + { + long nDiff = m_pTextView->GetStartDocPos().Y() - pScroll->GetThumbPos(); + GetTextView()->Scroll( 0, nDiff ); + m_pTextView->ShowCursor( false ); + pScroll->SetThumbPos( m_pTextView->GetStartDocPos().Y() ); + } + else + { + long nDiff = m_pTextView->GetStartDocPos().X() - pScroll->GetThumbPos(); + GetTextView()->Scroll( nDiff, 0 ); + m_pTextView->ShowCursor( false ); + pScroll->SetThumbPos( m_pTextView->GetStartDocPos().X() ); + } + 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 = static_cast(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! + 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( const OUString& rSource, sal_uInt16 nLineOff ) +{ + TextPortions aPortionList; + lcl_Highlight(rSource, 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 < rSource.getLength() ) ) + r.nEnd = rSource.getLength(); + } + } + + 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(&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( static_cast(pTextHint->GetValue()) ); + m_aSyntaxIdle.Start(); + } + break; + default: break; + } +} + +void SwSrcEditWindow::Invalidate(InvalidateFlags ) +{ + m_pOutWin->Invalidate(); + Window::Invalidate(); +} + +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, this); + } + else + aFont = OutputDevice::GetDefaultFont(DefaultFontType::SANS_UNICODE, + Application::GetSettings().GetLanguageTag().getLanguageType(), GetDefaultFontFlags::NONE, this); + sFontName = aFont.GetFamilyName(); + } + const SvxFontListItem* pFontListItem = + static_cast(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 000000000..6f8494601 --- /dev/null +++ b/sw/source/uibase/envelp/envimg.cxx @@ -0,0 +1,334 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _WIN32 +#define NEXTLINE "\r\n" +#else +#define NEXTLINE "\n" +#endif + +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 { + OUString sToken = sSenderToken.getToken( 0, ';', nSttPos ); + if (sToken == "COMPANY") + { + sal_Int32 nOldLen = sRet.getLength(); + sRet.append(rUserOpt.GetCompany()); + bLastLength = sRet.getLength() != nOldLen; + } + else if (sToken == "CR") + { + if(bLastLength) + sRet.append(NEXTLINE); + bLastLength = true; + } + else if (sToken == "FIRSTNAME") + sRet.append(rUserOpt.GetFirstName()); + else if (sToken == "LASTNAME") + sRet.append(rUserOpt.GetLastName()); + else if (sToken == "ADDRESS") + sRet.append(rUserOpt.GetStreet()); + else if (sToken == "COUNTRY") + sRet.append(rUserOpt.GetCountry()); + else if (sToken == "POSTALCODE") + sRet.append(rUserOpt.GetZip()); + else if (sToken == "CITY") + sRet.append(rUserOpt.GetCity()); + else if (sToken == "STATEPROV") + sRet.append(rUserOpt.GetState()); + else if (!sToken.isEmpty()) //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 +{ + const SwEnvItem& rEnv = static_cast( 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 aNames = GetPropertyNames(); + Sequence aValues = GetProperties(aNames); + EnableNotification(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: 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(pValues[nProp]); break;// "Inscription/UseSender", + case 3: + pValues[nProp] >>= m_aEnvItem.m_nAddrFromLeft;// "Format/AddresseeFromLeft", + m_aEnvItem.m_nAddrFromLeft = convertMm100ToTwip(m_aEnvItem.m_nAddrFromLeft); + break; + case 4: + pValues[nProp] >>= m_aEnvItem.m_nAddrFromTop; // "Format/AddresseeFromTop", + m_aEnvItem.m_nAddrFromTop = convertMm100ToTwip(m_aEnvItem.m_nAddrFromTop); + break; + case 5: + pValues[nProp] >>= m_aEnvItem.m_nSendFromLeft; // "Format/SenderFromLeft", + m_aEnvItem.m_nSendFromLeft = convertMm100ToTwip(m_aEnvItem.m_nSendFromLeft); + break; + case 6: + pValues[nProp] >>= m_aEnvItem.m_nSendFromTop;// "Format/SenderFromTop", + m_aEnvItem.m_nSendFromTop = convertMm100ToTwip(m_aEnvItem.m_nSendFromTop); + break; + case 7: + pValues[nProp] >>= m_aEnvItem.m_nWidth; // "Format/Width", + m_aEnvItem.m_nWidth = convertMm100ToTwip(m_aEnvItem.m_nWidth); + break; + case 8: + pValues[nProp] >>= m_aEnvItem.m_nHeight; // "Format/Height", + m_aEnvItem.m_nHeight = convertMm100ToTwip(m_aEnvItem.m_nHeight); + break; + case 9: + { + sal_Int32 nTemp = 0; + pValues[nProp] >>= nTemp; m_aEnvItem.m_eAlign = static_cast(nTemp); break;// "Print/Alignment", + } + case 10: m_aEnvItem.m_bPrintFromAbove = *o3tl::doAccess(pValues[nProp]); break;// "Print/FromAbove", + case 11: + pValues[nProp] >>= m_aEnvItem.m_nShiftRight; + m_aEnvItem.m_nShiftRight = convertMm100ToTwip(m_aEnvItem.m_nShiftRight);// "Print/Right", + break; + case 12: + pValues[nProp] >>= m_aEnvItem.m_nShiftDown; + m_aEnvItem.m_nShiftDown = convertMm100ToTwip(m_aEnvItem.m_nShiftDown); + break;// "Print/Down" + } + } + } + } +} + +SwEnvCfgItem::~SwEnvCfgItem() +{ +} + +void SwEnvCfgItem::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + Sequence 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 (convertTwipToMm100(m_aEnvItem.m_nAddrFromLeft)) ; break;// "Format/AddresseeFromLeft", + case 4: pValues[nProp] <<= static_cast (convertTwipToMm100(m_aEnvItem.m_nAddrFromTop)) ; break;// "Format/AddresseeFromTop", + case 5: pValues[nProp] <<= static_cast (convertTwipToMm100(m_aEnvItem.m_nSendFromLeft)) ; break;// "Format/SenderFromLeft", + case 6: pValues[nProp] <<= static_cast (convertTwipToMm100(m_aEnvItem.m_nSendFromTop)) ; break;// "Format/SenderFromTop", + case 7: pValues[nProp] <<= static_cast (convertTwipToMm100(m_aEnvItem.m_nWidth)) ; break;// "Format/Width", + case 8: pValues[nProp] <<= static_cast (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 (convertTwipToMm100(m_aEnvItem.m_nShiftRight));break; // "Print/Right", + case 12: pValues[nProp] <<= static_cast (convertTwipToMm100(m_aEnvItem.m_nShiftDown)); break;// "Print/Down" + } + } + PutProperties(aNames, aValues); +} + +void SwEnvCfgItem::Notify( const css::uno::Sequence< OUString >& ) {} + +Sequence 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 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(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 000000000..59c252be0 --- /dev/null +++ b/sw/source/uibase/envelp/labelcfg.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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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 lcl_CreatePropertyNames(const OUString& rPrefix) +{ + Sequence aProperties(2); + OUString* pProperties = aProperties.getArray(); + std::fill(aProperties.begin(), aProperties.end(), rPrefix); + + pProperties[ 0] += "Name"; + pProperties[ 1] += "Measure"; + return aProperties; +} + +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& rMan = GetNodeNames( OUString() ); + for ( const OUString& rManufacturer : rMan ) + { + const Sequence aLabels = GetNodeNames( rManufacturer ); + for( const OUString& rLabel : aLabels ) + { + OUString sPrefix = rManufacturer + "/" + rLabel + "/"; + Sequence aPropNames = lcl_CreatePropertyNames( sPrefix ); + Sequence 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 lcl_CreateSwLabRec(const OUString& rType, const OUString& rMeasure, const OUString& rManufacturer) +{ + std::unique_ptr 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.isEmpty() ? -1 : 0}; + while (nIdx>=0) + { + const OUString sToken(rMeasure.getToken(0, ';', nIdx)); + int nVal = sToken.toInt32(); + switch(nTok++) + { + case 0 : pNewRec->m_bCont = sToken[0] == 'C'; break; + case 1 : pNewRec->m_nHDist = convertMm100ToTwip(nVal); break; + case 2 : pNewRec->m_nVDist = convertMm100ToTwip(nVal); break; + case 3 : pNewRec->m_nWidth = convertMm100ToTwip(nVal); break; + case 4 : pNewRec->m_nHeight = convertMm100ToTwip(nVal); break; + case 5 : pNewRec->m_nLeft = convertMm100ToTwip(nVal); break; + case 6 : pNewRec->m_nUpper = convertMm100ToTwip(nVal); break; + case 7 : pNewRec->m_nCols = nVal; break; + case 8 : pNewRec->m_nRows = nVal; break; + case 9 : pNewRec->m_nPWidth = convertMm100ToTwip(nVal); break; + case 10 : pNewRec->m_nPHeight = convertMm100ToTwip(nVal); 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 lcl_CreateProperties( + Sequence const & rPropNames, OUString& rMeasure, const SwLabRec& rRec) +{ + const OUString* pNames = rPropNames.getConstArray(); + Sequence 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 ? OUStringLiteral( "C" ) : OUStringLiteral( "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) +{ + return ( ( m_aLabels.find(rManufacturer) != m_aLabels.end() ) && + ( m_aLabels[rManufacturer].find(rType) != m_aLabels[rManufacturer].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 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 aLabels = GetNodeNames( sManufacturer ); + for (const OUString& rLabel : aLabels) + { + OUString sPrefix = sManufacturer + "/" + rLabel + "/"; + Sequence aProperties { sPrefix }; + aProperties.getArray()[0] += "Name"; + Sequence 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 aPropNames = lcl_CreatePropertyNames( sPrefix ); + OUString sMeasure; + Sequence 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 000000000..03a38a853 --- /dev/null +++ b/sw/source/uibase/envelp/labimg.cxx @@ -0,0 +1,463 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include + +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 +{ + const SwLabItem& rLab = static_cast( 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 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 = bIsLabel ? 0 : 34; + const int nLabelCount = bIsLabel ? 20 : 17; + Sequence 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")), + bIsLabel(bLabel) +{ + Sequence aNames = GetPropertyNames(); + Sequence 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 contiuous switch an offset is added + if(nProp == 17 && !bIsLabel) + nProperty += 3; + if(nProperty >= 20) + bNoConfigValues = false; + switch(nProperty) + { + case 0: aItem.m_bCont = *o3tl::doAccess(pValues[nProp]); break;// "Medium/Continuous", + case 1: pValues[nProp] >>= aItem.m_aMake; break;// "Medium/Brand", + case 2: pValues[nProp] >>= aItem.m_aType; break;// "Medium/Type", + case 3: pValues[nProp] >>= aItem.m_nCols; break;// "Format/Column", + case 4: pValues[nProp] >>= aItem.m_nRows; break;// "Format/Row", + case 5: + pValues[nProp] >>= aItem.m_lHDist; + aItem.m_lHDist = convertMm100ToTwip(aItem.m_lHDist); + break;// "Format/HorizontalDistance", + case 6: + pValues[nProp] >>= aItem.m_lVDist; + aItem.m_lVDist = convertMm100ToTwip(aItem.m_lVDist); + break;// "Format/VerticalDistance", + case 7: + pValues[nProp] >>= aItem.m_lWidth; + aItem.m_lWidth = convertMm100ToTwip(aItem.m_lWidth); + break;// "Format/Width", + case 8: + pValues[nProp] >>= aItem.m_lHeight; + aItem.m_lHeight = convertMm100ToTwip(aItem.m_lHeight); + break;// "Format/Height", + case 9: + pValues[nProp] >>= aItem.m_lLeft; + aItem.m_lLeft = convertMm100ToTwip(aItem.m_lLeft); + break;// "Format/LeftMargin", + case 10: + pValues[nProp] >>= aItem.m_lUpper; + aItem.m_lUpper = convertMm100ToTwip(aItem.m_lUpper); + break;// "Format/TopMargin", + case 11: + pValues[nProp] >>= aItem.m_lPWidth; + aItem.m_lPWidth = convertMm100ToTwip(aItem.m_lPWidth); + break;// "Format/PageWidth", + case 12: + pValues[nProp] >>= aItem.m_lPHeight; + aItem.m_lPHeight = convertMm100ToTwip(aItem.m_lPHeight); + break;// "Format/PageHeight", + case 13: aItem.m_bSynchron = *o3tl::doAccess(pValues[nProp]); break;// "Option/Synchronize", + case 14: aItem.m_bPage = *o3tl::doAccess(pValues[nProp]); break;// "Option/Page", + case 15: pValues[nProp] >>= aItem.m_nCol; break;// "Option/Column", + case 16: pValues[nProp] >>= aItem.m_nRow; break;// "Option/Row" + case 17: aItem.m_bAddr = *o3tl::doAccess(pValues[nProp]); break;// "Inscription/UseAddress", + case 18: pValues[nProp] >>= aItem.m_aWriting; break;// "Inscription/Address", + case 19: pValues[nProp] >>= aItem.m_sDBName; break;// "Inscription/Database" + case 20: pValues[nProp] >>= aItem.m_aPrivFirstName; break;// "PrivateAddress/FirstName", + case 21: pValues[nProp] >>= aItem.m_aPrivName; break;// "PrivateAddress/Name", + case 22: pValues[nProp] >>= aItem.m_aPrivShortCut; break;// "PrivateAddress/ShortCut", + case 23: pValues[nProp] >>= aItem.m_aPrivFirstName2; break;// "PrivateAddress/SecondFirstName", + case 24: pValues[nProp] >>= aItem.m_aPrivName2; break;// "PrivateAddress/SecondName", + case 25: pValues[nProp] >>= aItem.m_aPrivShortCut2; break;// "PrivateAddress/SecondShortCut", + case 26: pValues[nProp] >>= aItem.m_aPrivStreet; break;// "PrivateAddress/Street", + case 27: pValues[nProp] >>= aItem.m_aPrivZip; break;// "PrivateAddress/Zip", + case 28: pValues[nProp] >>= aItem.m_aPrivCity; break;// "PrivateAddress/City", + case 29: pValues[nProp] >>= aItem.m_aPrivCountry; break;// "PrivateAddress/Country", + case 30: pValues[nProp] >>= aItem.m_aPrivState; break;// "PrivateAddress/State", + case 31: pValues[nProp] >>= aItem.m_aPrivTitle; break;// "PrivateAddress/Title", + case 32: pValues[nProp] >>= aItem.m_aPrivProfession; break;// "PrivateAddress/Profession", + case 33: pValues[nProp] >>= aItem.m_aPrivPhone; break;// "PrivateAddress/Phone", + case 34: pValues[nProp] >>= aItem.m_aPrivMobile; break;// "PrivateAddress/Mobile", + case 35: pValues[nProp] >>= aItem.m_aPrivFax; break;// "PrivateAddress/Fax", + case 36: pValues[nProp] >>= aItem.m_aPrivWWW; break;// "PrivateAddress/WebAddress", + case 37: pValues[nProp] >>= aItem.m_aPrivMail; break;// "PrivateAddress/Email", + case 38: pValues[nProp] >>= aItem.m_aCompCompany; break;// "BusinessAddress/Company", + case 39: pValues[nProp] >>= aItem.m_aCompCompanyExt; break;// "BusinessAddress/CompanyExt", + case 40: pValues[nProp] >>= aItem.m_aCompSlogan; break;// "BusinessAddress/Slogan", + case 41: pValues[nProp] >>= aItem.m_aCompStreet; break;// "BusinessAddress/Street", + case 42: pValues[nProp] >>= aItem.m_aCompZip; break;// "BusinessAddress/Zip", + case 43: pValues[nProp] >>= aItem.m_aCompCity; break;// "BusinessAddress/City", + case 44: pValues[nProp] >>= aItem.m_aCompCountry; break;// "BusinessAddress/Country", + case 45: pValues[nProp] >>= aItem.m_aCompState; break;// "BusinessAddress/State", + case 46: pValues[nProp] >>= aItem.m_aCompPosition; break;// "BusinessAddress/Position", + case 47: pValues[nProp] >>= aItem.m_aCompPhone; break;// "BusinessAddress/Phone", + case 48: pValues[nProp] >>= aItem.m_aCompMobile; break;// "BusinessAddress/Mobile", + case 49: pValues[nProp] >>= aItem.m_aCompFax; break;// "BusinessAddress/Fax", + case 50: pValues[nProp] >>= aItem.m_aCompWWW; break;// "BusinessAddress/WebAddress", + case 51: pValues[nProp] >>= aItem.m_aCompMail; break;// "BusinessAddress/Email", + case 52: pValues[nProp] >>= aItem.m_sGlossaryGroup; break;// "AutoText/Group" + case 53: pValues[nProp] >>= aItem.m_sGlossaryBlockName; break;// "AutoText/Block" + } + } + } + } + + if(bIsLabel || !bNoConfigValues) + return; + + SvtUserOptions& rUserOpt = SW_MOD()->GetUserOptions(); + aItem.m_aPrivFirstName = rUserOpt.GetFirstName(); + aItem.m_aPrivName = rUserOpt.GetLastName(); + aItem.m_aPrivShortCut = rUserOpt.GetID(); + aItem.m_aCompCompany = rUserOpt.GetCompany(); + aItem.m_aCompStreet = aItem.m_aPrivStreet = rUserOpt.GetStreet(); + + aItem.m_aCompCountry = aItem.m_aPrivCountry = rUserOpt.GetCountry(); + aItem.m_aCompZip = aItem.m_aPrivZip= rUserOpt.GetZip(); + aItem.m_aCompCity = aItem.m_aPrivCity = rUserOpt.GetCity(); + aItem.m_aPrivTitle = rUserOpt.GetTitle(); + aItem.m_aCompPosition = rUserOpt.GetPosition(); + aItem.m_aPrivPhone = rUserOpt.GetTelephoneHome(); + aItem.m_aCompPhone = rUserOpt.GetTelephoneWork(); + aItem.m_aCompFax = aItem.m_aPrivFax = rUserOpt.GetFax(); + aItem.m_aCompMail = aItem.m_aPrivMail = rUserOpt.GetEmail(); + aItem.m_aCompState = aItem.m_aPrivState = rUserOpt.GetState(); + aItem.m_bSynchron = true; + SetModified(); + +} + +void SwLabCfgItem::Notify( const css::uno::Sequence< OUString >& ) {} + +void SwLabCfgItem::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0, nProperty = 0; nProp < aNames.getLength(); nProp++, nProperty++) + { + //to have a contiuous switch an offset is added + if(nProp == 17 && !bIsLabel) + nProperty += 3; + switch(nProperty) + { + case 0: pValues[nProp] <<= aItem.m_bCont; break;// "Medium/Continuous", + case 1: pValues[nProp] <<= aItem.m_aMake; break;// "Medium/Brand", + case 2: pValues[nProp] <<= aItem.m_aType; break;// "Medium/Type", + case 3: pValues[nProp] <<= aItem.m_nCols; break;// "Format/Column", + case 4: pValues[nProp] <<= aItem.m_nRows; break;// "Format/Row", + case 5: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lHDist));break;// "Format/HorizontalDistance", + case 6: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lVDist));break;// "Format/VerticalDistance", + case 7: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lWidth)); break;// "Format/Width", + case 8: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lHeight)); break;// "Format/Height", + case 9: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lLeft)); break;// "Format/LeftMargin", + case 10: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lUpper)); break;// "Format/TopMargin", + case 11: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lPWidth)); break;// "Format/Page Width", + case 12: pValues[nProp] <<= static_cast(convertTwipToMm100(aItem.m_lPHeight)); break;// "Format/PageHeight", + case 13: pValues[nProp] <<= aItem.m_bSynchron; break;// "Option/Synchronize", + case 14: pValues[nProp] <<= aItem.m_bPage; break;// "Option/Page", + case 15: pValues[nProp] <<= aItem.m_nCol; break;// "Option/Column", + case 16: pValues[nProp] <<= aItem.m_nRow; break;// "Option/Row" + case 17: pValues[nProp] <<= aItem.m_bAddr; break;// "Inscription/UseAddress", + case 18: pValues[nProp] <<= aItem.m_aWriting; break;// "Inscription/Address", + case 19: pValues[nProp] <<= aItem.m_sDBName; break;// "Inscription/Database" + case 20: pValues[nProp] <<= aItem.m_aPrivFirstName; break;// "PrivateAddress/FirstName", + case 21: pValues[nProp] <<= aItem.m_aPrivName; break;// "PrivateAddress/Name", + case 22: pValues[nProp] <<= aItem.m_aPrivShortCut; break;// "PrivateAddress/ShortCut", + case 23: pValues[nProp] <<= aItem.m_aPrivFirstName2; break;// "PrivateAddress/SecondFirstName", + case 24: pValues[nProp] <<= aItem.m_aPrivName2; break;// "PrivateAddress/SecondName", + case 25: pValues[nProp] <<= aItem.m_aPrivShortCut2; break;// "PrivateAddress/SecondShortCut", + case 26: pValues[nProp] <<= aItem.m_aPrivStreet; break;// "PrivateAddress/Street", + case 27: pValues[nProp] <<= aItem.m_aPrivZip; break;// "PrivateAddress/Zip", + case 28: pValues[nProp] <<= aItem.m_aPrivCity; break;// "PrivateAddress/City", + case 29: pValues[nProp] <<= aItem.m_aPrivCountry; break;// "PrivateAddress/Country", + case 30: pValues[nProp] <<= aItem.m_aPrivState; break;// "PrivateAddress/State", + case 31: pValues[nProp] <<= aItem.m_aPrivTitle; break;// "PrivateAddress/Title", + case 32: pValues[nProp] <<= aItem.m_aPrivProfession; break;// "PrivateAddress/Profession", + case 33: pValues[nProp] <<= aItem.m_aPrivPhone; break;// "PrivateAddress/Phone", + case 34: pValues[nProp] <<= aItem.m_aPrivMobile; break;// "PrivateAddress/Mobile", + case 35: pValues[nProp] <<= aItem.m_aPrivFax; break;// "PrivateAddress/Fax", + case 36: pValues[nProp] <<= aItem.m_aPrivWWW; break;// "PrivateAddress/WebAddress", + case 37: pValues[nProp] <<= aItem.m_aPrivMail; break;// "PrivateAddress/Email", + case 38: pValues[nProp] <<= aItem.m_aCompCompany; break;// "BusinessAddress/Company", + case 39: pValues[nProp] <<= aItem.m_aCompCompanyExt; break;// "BusinessAddress/CompanyExt", + case 40: pValues[nProp] <<= aItem.m_aCompSlogan; break;// "BusinessAddress/Slogan", + case 41: pValues[nProp] <<= aItem.m_aCompStreet; break;// "BusinessAddress/Street", + case 42: pValues[nProp] <<= aItem.m_aCompZip; break;// "BusinessAddress/Zip", + case 43: pValues[nProp] <<= aItem.m_aCompCity; break;// "BusinessAddress/City", + case 44: pValues[nProp] <<= aItem.m_aCompCountry; break;// "BusinessAddress/Country", + case 45: pValues[nProp] <<= aItem.m_aCompState; break;// "BusinessAddress/State", + case 46: pValues[nProp] <<= aItem.m_aCompPosition; break;// "BusinessAddress/Position", + case 47: pValues[nProp] <<= aItem.m_aCompPhone; break;// "BusinessAddress/Phone", + case 48: pValues[nProp] <<= aItem.m_aCompMobile; break;// "BusinessAddress/Mobile", + case 49: pValues[nProp] <<= aItem.m_aCompFax; break;// "BusinessAddress/Fax", + case 50: pValues[nProp] <<= aItem.m_aCompWWW; break;// "BusinessAddress/WebAddress", + case 51: pValues[nProp] <<= aItem.m_aCompMail; break;// "BusinessAddress/Email", + case 52: pValues[nProp] <<= aItem.m_sGlossaryGroup; break;// "AutoText/Group" + case 53: pValues[nProp] <<= 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 000000000..009525d02 --- /dev/null +++ b/sw/source/uibase/envelp/syncbtn.cxx @@ -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 . + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +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(pBindings, this, _pParent->GetFrameWeld())); + SwSyncBtnDlg* pBtnDlg = static_cast(GetController().get()); + + if (!pInfo->aSize.Width() || !pInfo->aSize.Height()) + { + weld::Dialog* pDlg = pBtnDlg->getDialog(); + Point aPos; + + SwView* pActiveView = ::GetActiveView(); + if (pActiveView) + { + const SwEditWin &rEditWin = pActiveView->GetEditWin(); + aPos = rEditWin.OutputToScreenPixel(Point(0, 0)); + } + else + aPos = _pParent->OutputToScreenPixel(Point(0, 0)); + + WindowStateData aState; + aState.SetMask(WindowStateMask::Pos); + aState.SetX(aPos.X()); + aState.SetY(aPos.Y()); + 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) +{ + SfxViewFrame::Current()->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 000000000..ff6b78296 --- /dev/null +++ b/sw/source/uibase/fldui/fldmgr.cxx @@ -0,0 +1,1850 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 +}; + +static const sal_uInt16 VF_COUNT = 1; // { 0 } +static const sal_uInt16 VF_USR_COUNT = 2; // { 0, nsSwExtendedSubType::SUB_CMD } +static const sal_uInt16 VF_DB_COUNT = 1; // { nsSwExtendedSubType::SUB_OWN_FMT } + +static const char* 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 +}; + +static const char* FMT_AUTHOR_ARY[] = +{ + FMT_AUTHOR_NAME, + FMT_AUTHOR_SCUT +}; + +static const char* FLD_DATE_ARY[] = +{ + FLD_DATE_FIX, + FLD_DATE_STD, +}; + +static const char* FLD_TIME_ARY[] = +{ + FLD_TIME_FIX, + FLD_TIME_STD +}; + +static const char* 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 +}; + +static const char* FMT_FF_ARY[] = +{ + FMT_FF_NAME, + FMT_FF_PATHNAME, + FMT_FF_PATH, + FMT_FF_NAME_NOEXT, + FMT_FF_UI_NAME, + FMT_FF_UI_RANGE +}; + +static const char* FLD_STAT_ARY[] = +{ + FLD_STAT_PAGE, + FLD_STAT_PARA, + FLD_STAT_WORD, + FLD_STAT_CHAR, + FLD_STAT_TABLE, + FLD_STAT_GRF, + FLD_STAT_OBJ +}; + +static const char* FMT_CHAPTER_ARY[] = +{ + FMT_CHAPTER_NO, + FMT_CHAPTER_NAME, + FMT_CHAPTER_NAMENO, + FMT_CHAPTER_NO_NOSEPARATOR +}; + +static const char* FLD_INPUT_ARY[] = +{ + FLD_INPUT_TEXT +}; + +static const char* FMT_MARK_ARY[] = +{ + FMT_MARK_TEXT, + FMT_MARK_TABLE, + FMT_MARK_FRAME, + FMT_MARK_GRAFIC, + FMT_MARK_OLE +}; + +static const char* 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 +}; + +static const char* FMT_REG_ARY[] = +{ + FMT_REG_AUTHOR, + FMT_REG_TIME, + FMT_REG_DATE +}; + +static const char* FMT_DBFLD_ARY[] = +{ + FMT_DBFLD_DB, + FMT_DBFLD_SYS +}; + +static const char* FMT_SETVAR_ARY[] = +{ + FMT_SETVAR_SYS, + FMT_SETVAR_TEXT +}; + +static const char* FMT_GETVAR_ARY[] = +{ + FMT_GETVAR_TEXT, + FMT_GETVAR_NAME +}; + +static const char* FMT_DDE_ARY[] = +{ + FMT_DDE_NORMAL, + FMT_DDE_HOT +}; + +static const char* FLD_PAGEREF_ARY[] = +{ + FLD_PAGEREF_OFF, + FLD_PAGEREF_ON +}; + +static const char* FMT_USERVAR_ARY[] = +{ + FMT_USERVAR_TEXT, + FMT_USERVAR_CMD +}; + +namespace { + +// field types and subtypes +struct SwFieldPack +{ + SwFieldTypesEnum nTypeId; + + const char** pSubTypeResIds; + size_t nSubTypeLength; + + const char** pFormatResIds; + size_t nFormatLength; +}; + +} + +// strings and formats +static const SwFieldPack aSwFields[] = +{ + // Document + { SwFieldTypesEnum::ExtendedUser, FLD_EU_ARY, SAL_N_ELEMENTS(FLD_EU_ARY), nullptr, 0 }, + { SwFieldTypesEnum::Author, nullptr, 0, FMT_AUTHOR_ARY, SAL_N_ELEMENTS(FMT_AUTHOR_ARY) }, + { SwFieldTypesEnum::Date, FLD_DATE_ARY, SAL_N_ELEMENTS(FLD_DATE_ARY), nullptr, 0 }, + { SwFieldTypesEnum::Time, FLD_TIME_ARY, SAL_N_ELEMENTS(FLD_TIME_ARY), nullptr, 0 }, + { SwFieldTypesEnum::PageNumber, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) -1 }, + { SwFieldTypesEnum::NextPage, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) }, + { SwFieldTypesEnum::PreviousPage, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) }, + { SwFieldTypesEnum::Filename, nullptr, 0, FMT_FF_ARY, SAL_N_ELEMENTS(FMT_FF_ARY) }, + { SwFieldTypesEnum::DocumentStatistics, FLD_STAT_ARY, SAL_N_ELEMENTS(FLD_STAT_ARY), FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) -1 }, + + { SwFieldTypesEnum::Chapter, nullptr, 0, FMT_CHAPTER_ARY, SAL_N_ELEMENTS(FMT_CHAPTER_ARY) }, + { SwFieldTypesEnum::TemplateName, nullptr, 0, FMT_FF_ARY, SAL_N_ELEMENTS(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, SAL_N_ELEMENTS(FLD_INPUT_ARY), nullptr, 0 }, + { SwFieldTypesEnum::Macro, nullptr, 0, nullptr, 0 }, + { SwFieldTypesEnum::JumpEdit, nullptr, 0, FMT_MARK_ARY, SAL_N_ELEMENTS(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, SAL_N_ELEMENTS(FMT_REF_ARY) }, + + // DocInformation + { SwFieldTypesEnum::DocumentInfo, nullptr, 0, FMT_REG_ARY, SAL_N_ELEMENTS(FMT_REG_ARY) }, + + // Database + { SwFieldTypesEnum::Database, nullptr, 0, FMT_DBFLD_ARY, SAL_N_ELEMENTS(FMT_DBFLD_ARY) }, + { SwFieldTypesEnum::DatabaseNextSet, nullptr, 0, nullptr, 0 }, + { SwFieldTypesEnum::DatabaseNumberSet, nullptr, 0, nullptr, 0 }, + { SwFieldTypesEnum::DatabaseSetNumber, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) - 2 }, + { SwFieldTypesEnum::DatabaseName, nullptr, 0, nullptr, 0 }, + + // Variables + { SwFieldTypesEnum::Set, nullptr, 0, FMT_SETVAR_ARY, SAL_N_ELEMENTS(FMT_SETVAR_ARY) }, + + { SwFieldTypesEnum::Get, nullptr, 0, FMT_GETVAR_ARY, SAL_N_ELEMENTS(FMT_GETVAR_ARY) }, + { SwFieldTypesEnum::DDE, nullptr, 0, FMT_DDE_ARY, SAL_N_ELEMENTS(FMT_DDE_ARY) }, + { SwFieldTypesEnum::Formel, nullptr, 0, FMT_GETVAR_ARY, SAL_N_ELEMENTS(FMT_GETVAR_ARY) }, + { SwFieldTypesEnum::Input, FLD_INPUT_ARY, SAL_N_ELEMENTS(FLD_INPUT_ARY), nullptr, 0 }, + { SwFieldTypesEnum::Sequence, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) - 2 }, + { SwFieldTypesEnum::SetRefPage, FLD_PAGEREF_ARY, SAL_N_ELEMENTS(FLD_PAGEREF_ARY),nullptr, 0 }, + { SwFieldTypesEnum::GetRefPage, nullptr, 0, FMT_NUM_ARY, SAL_N_ELEMENTS(FMT_NUM_ARY) - 1 }, + { SwFieldTypesEnum::User, nullptr, 0, FMT_USERVAR_ARY, SAL_N_ELEMENTS(FMT_USERVAR_ARY) } +}; + +// access to the shell +static SwWrtShell* lcl_GetShell() +{ + SwView* pView; + if ( nullptr != (pView = ::GetActiveView()) ) + return pView->GetWrtShellPtr(); + OSL_FAIL("no current shell found!"); + 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( const OUString& 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(); + m_nCurFormat = 0; + + if(!m_pCurField) + return nullptr; + + // preprocess current values; determine parameter 1 and parameter 2 + // as well as the format + const SwFieldTypesEnum nTypeId = m_pCurField->GetTypeId(); + + m_nCurFormat = m_pCurField->GetFormat(); + m_aCurPar1 = m_pCurField->GetPar1(); + m_aCurPar2 = m_pCurField->GetPar2(); + + switch( nTypeId ) + { + case SwFieldTypesEnum::PageNumber: + case SwFieldTypesEnum::NextPage: + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::GetRefPage: + if( m_nCurFormat == SVX_NUM_PAGEDESC ) + m_nCurFormat -= 2; + break; + default: break; + } + 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; +} + +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& rToFill) +{ + SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell(); + OSL_ENSURE(pSh, "no SwWrtShell found"); + if(pSh) + { + 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(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) || + + (nTypeId == SwFieldTypesEnum::Set && nWhich == SwFieldIds::SetExp && + !(static_cast(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) || + + (nTypeId == SwFieldTypesEnum::Sequence && nWhich == SwFieldIds::SetExp && + (static_cast(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) || + + ((nTypeId == SwFieldTypesEnum::Input || nTypeId == SwFieldTypesEnum::Formel) && + (nWhich == SwFieldIds::User || + (nWhich == SwFieldIds::SetExp && + !(static_cast(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 char** pStart = aSwFields[nPos].pFormatResIds; + if (!pStart) + return nCount; + + if (strcmp(*pStart, FMT_GETVAR_ARY[0]) == 0 || strcmp(*pStart, FMT_SETVAR_ARY[0]) == 0) + return VF_COUNT; + else if (strcmp(*pStart, FMT_USERVAR_ARY[0]) == 0) + return VF_USR_COUNT; + else if (strcmp(*pStart, FMT_DBFLD_ARY[0]) == 0) + return VF_DB_COUNT; + else if (strcmp(*pStart, FMT_NUM_ARY[0]) == 0) + { + GetNumberingInfo(); + if(m_xNumberingInfo.is()) + { + Sequence 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 char** pStart = aSwFields[nPos].pFormatResIds; + if (!pStart) + return OUString(); + + if (SwFieldTypesEnum::Author == nTypeId || SwFieldTypesEnum::Filename == nTypeId) + nFormatId &= ~static_cast(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()) + { + Sequence 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 = static_cast(nFormatId); + switch( nTypeId ) + { + case SwFieldTypesEnum::DocumentInfo: + { + const OString 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 OString 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()) + { + Sequence 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(nFormatId) - nOffset) + { + nId = nCurrent; + break; + } + ++nValidEntry; + } + } + } + break; + } + case SwFieldTypesEnum::DDE: + { + const OString sId(aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId]); + if (sId == FMT_DDE_NORMAL) + nId = static_cast(SfxLinkUpdateMode::ONCALL); + else if (sId == FMT_DDE_HOT) + nId = static_cast(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( + const SwInsertField_Data& rData) +{ + std::unique_ptr 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(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(pCurShell->GetFieldType(0, SwFieldIds::Script)); + pField.reset(new SwScriptField(pType, rData.m_sPar1, rData.m_sPar2, static_cast(nFormatId))); + break; + } + + case SwFieldTypesEnum::CombinedChars: + { + SwCombinedCharFieldType* pType = static_cast( + pCurShell->GetFieldType( 0, SwFieldIds::CombinedChars )); + pField.reset(new SwCombinedCharField( pType, rData.m_sPar1 )); + } + break; + + case SwFieldTypesEnum::Authority: + { + SwAuthorityFieldType* pType = + static_cast(pCurShell->GetFieldType(0, SwFieldIds::TableOfAuthorities)); + if (!pType) + { + SwAuthorityFieldType const type(pCurShell->GetDoc()); + pType = static_cast( + 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( 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( pCurShell->GetFieldType(0, SwFieldIds::Filename) ); + pField.reset(new SwFileNameField(pTyp, nFormatId)); + break; + } + + case SwFieldTypesEnum::TemplateName: + { + SwTemplNameFieldType* pTyp = + static_cast( pCurShell->GetFieldType(0, SwFieldIds::TemplateName) ); + pField.reset(new SwTemplNameField(pTyp, nFormatId)); + break; + } + + case SwFieldTypesEnum::Chapter: + { + sal_uInt16 nByte = static_cast(rData.m_sPar2.toInt32()); + SwChapterFieldType* pTyp = + static_cast( 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(pField.get())->SetLevel(static_cast(nByte)); + break; + } + + case SwFieldTypesEnum::NextPage: + case SwFieldTypesEnum::PreviousPage: + case SwFieldTypesEnum::PageNumber: + { + short nOff = static_cast(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( 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(pField.get())->SetUserString( rData.m_sPar2 ); + break; + } + + case SwFieldTypesEnum::DocumentStatistics: + { + SwDocStatFieldType* pTyp = + static_cast( pCurShell->GetFieldType(0, SwFieldIds::DocStat) ); + pField.reset(new SwDocStatField(pTyp, nSubType, nFormatId)); + break; + } + + case SwFieldTypesEnum::Author: + { + SwAuthorFieldType* pTyp = + static_cast( pCurShell->GetFieldType(0, SwFieldIds::Author) ); + pField.reset(new SwAuthorField(pTyp, nFormatId)); + break; + } + + case SwFieldTypesEnum::ConditionalText: + case SwFieldTypesEnum::HiddenText: + { + SwHiddenTextFieldType* pTyp = + static_cast( 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( 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 ) ) + { + pCurShell->SetAttrItem( SwFormatRefMark( rData.m_sPar1 ) ); + return true; + } + return false; + } + + case SwFieldTypesEnum::GetRef: + { + SwGetRefFieldType* pTyp = + static_cast( pCurShell->GetFieldType(0, SwFieldIds::GetRef) ); + sal_uInt16 nSeqNo = static_cast(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, 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(nFormatId) ); + SwDDEFieldType* pTyp = static_cast( pCurShell->InsertFieldType( aType ) ); + pField.reset(new SwDDEField( pTyp )); + break; + } + + case SwFieldTypesEnum::Macro: + { + SwMacroFieldType* pTyp = + static_cast(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(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( pCurShell->GetFieldType( + 0, SwFieldIds::DocInfo ) ); + pField.reset(new SwDocInfoField(pTyp, nSubType, rData.m_sPar1, nFormatId)); + break; + } + + case SwFieldTypesEnum::ExtendedUser: + { + SwExtUserFieldType* pTyp = static_cast( pCurShell->GetFieldType( + 0, SwFieldIds::ExtUser) ); + pField.reset(new SwExtUserField(pTyp, nSubType, nFormatId)); + break; + } + + case SwFieldTypesEnum::Database: + { +#if HAVE_FEATURE_DBCONNECTIVITY + 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 = rData.m_sPar1.getToken(0, DB_DELIM, nIdx).toInt32(); + sPar1 = rData.m_sPar1.getToken(0, DB_DELIM, nIdx); + } + + if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData) + pCurShell->ChgDBData(aDBData); + + SwDBFieldType* pTyp = static_cast(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; + rData.m_aDBConnection >>= xConnection; + Reference 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 + SwDBData aDBData; + + // extract DBName from rData.m_sPar1. Format: DBName.TableName.CommandType.ExpStrg + sal_Int32 nTablePos = rData.m_sPar1.indexOf(DB_DELIM); + sal_Int32 nCmdTypePos = -1; + sal_Int32 nExpPos = -1; + + if (nTablePos>=0) + { + aDBData.sDataSource = rData.m_sPar1.copy(0, nTablePos++); + 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 = rData.m_sPar1.copy(nCmdTypePos, nExpPos++ - nCmdTypePos).toInt32(); + } + } + } + + 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(pCurShell->GetFieldType(0, SwFieldIds::DatabaseName)); + pField.reset(new SwDBNameField(pTyp, aDBData)); + + break; + } + case SwFieldTypesEnum::DatabaseNextSet: + { + SwDBNextSetFieldType* pTyp = static_cast(pCurShell->GetFieldType( + 0, SwFieldIds::DbNextSet) ); + pField.reset(new SwDBNextSetField(pTyp, sPar1, aDBData)); + bExp = true; + break; + } + case SwFieldTypesEnum::DatabaseNumberSet: + { + SwDBNumSetFieldType* pTyp = static_cast( 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( + 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( pCurShell->GetFieldType(SwFieldIds::User, rData.m_sPar1) ); + + // only if existing + if(!pTyp) + { + pTyp = static_cast( 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( + pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1) ); + + // no Expression Type with this name existing -> create + if(pTyp) + { + std::unique_ptr 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( 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( pCurShell->InsertFieldType( + SwSetExpFieldType(pCurShell->GetDoc(), rData.m_sPar1) ) ); + + std::unique_ptr 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( 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( + pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1)); + + if(pSetTyp) + { + SwGetExpFieldType* pTyp = static_cast( 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 }); + } + + SfxItemSet aBoxSet( pCurShell->GetAttrPool(), + svl::Items{} ); + + 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( + 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( + pCurShell->GetFieldType( 0, SwFieldIds::RefPageSet ) ), + static_cast(rData.m_sPar2.toInt32()), 0 != nSubType ) ); + bPageVar = true; + break; + + case SwFieldTypesEnum::GetRefPage: + pField.reset( new SwRefPageGetField( static_cast( + 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 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(pField.get())->SetItems(aEntries); + static_cast(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; + break; + + 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(); + + pCurShell->Insert(*pField, rData.m_pAnnotationRange.get()); + + if (SwFieldTypesEnum::Input == rData.m_nTypeId) + { + pCurShell->Push(); + + // start dialog, not before the field is inserted tdf#99529 + pCurShell->Left(CRSR_SKIP_CHARS, + false, (INP_VAR == (nSubType & 0xff)) ? 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(CRSR_SKIP_CHARS, false, 1, false ); + pCurShell->UpdateOneField(*pField); + pCurShell->Right(CRSR_SKIP_CHARS, false, 1, false ); + } + else if( bPageVar ) + static_cast(pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ))->UpdateFields(); + else if( SwFieldTypesEnum::GetRef == rData.m_nTypeId ) + pField->GetTyp()->ModifyNotification( nullptr, nullptr ); + + // delete temporary field + pField.reset(); + + pCurShell->EndAllAction(); + return true; +} + +// fields update +void SwFieldMgr::UpdateCurField(sal_uInt32 nFormat, + const OUString& rPar1, + const OUString& rPar2, + std::unique_ptr 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(rPar2.toInt32()); + nByte = std::max(sal_uInt16(1), nByte); + nByte = std::min(nByte, sal_uInt16(MAXLEVEL)); + nByte -= 1; + static_cast(pTmpField.get())->SetLevel(static_cast(nByte)); + bSetPar2 = false; + break; + } + + case SwFieldTypesEnum::Script: + static_cast(pTmpField.get())->SetCodeURL(static_cast(nFormat)); + break; + + case SwFieldTypesEnum::NextPage: + if( SVX_NUM_CHAR_SPECIAL == nFormat ) + { + static_cast(m_pCurField)->SetUserString( sPar2 ); + sPar2 = "1"; + } + else + { + if( nFormat + 2 == SVX_NUM_PAGEDESC ) + nFormat = SVX_NUM_PAGEDESC; + short nOff = static_cast(sPar2.toInt32()); + nOff += 1; + sPar2 = OUString::number(nOff); + } + break; + + case SwFieldTypesEnum::PreviousPage: + if( SVX_NUM_CHAR_SPECIAL == nFormat ) + { + static_cast(m_pCurField)->SetUserString( sPar2 ); + sPar2 = "-1"; + } + else + { + if( nFormat + 2 == SVX_NUM_PAGEDESC ) + nFormat = SVX_NUM_PAGEDESC; + short nOff = static_cast(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; + static_cast(pTmpField.get())->SetSubType( static_cast(rPar2.toInt32()) ); + const sal_Int32 nPos = rPar2.indexOf( '|' ); + if( nPos>=0 ) + static_cast(pTmpField.get())->SetSeqNo( static_cast(rPar2.copy( nPos + 1 ).toInt32())); + } + break; + case SwFieldTypesEnum::Dropdown: + { + sal_Int32 nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM); + Sequence 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(pTmpField.get())->SetItems(aEntries); + static_cast(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(pTmpField.get()); + SwAuthorityFieldType* pAuthorityType = static_cast(pType); + rtl::Reference xTempEntry(new SwAuthEntry); + for( sal_Int32 i = 0, nIdx = 0; i < AUTH_FIELD_END; ++i ) + xTempEntry->SetAuthorField( static_cast(i), + rPar1.getToken( 0, TOX_STYLE_DELIMITER, nIdx )); + 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 char* 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; + SwFieldType::s_pFieldNames->reserve(SAL_N_ELEMENTS(coFieldNms)); + for (const char* 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 const & SwFieldMgr::GetNumberingInfo() const +{ + if(!m_xNumberingInfo.is()) + { + Reference xContext( ::comphelper::getProcessComponentContext() ); + Reference xDefNum = text::DefaultNumberingProvider::create(xContext); + const_cast(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 000000000..a2a41fa34 --- /dev/null +++ b/sw/source/uibase/fldui/fldwrap.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + +#include + +SFX_IMPL_CHILDWINDOW_WITHID(SwFieldDlgWrapper, FN_INSERT_FIELD) + +SwChildWinWrapper::SwChildWinWrapper(vcl::Window *pParentWindow, sal_uInt16 nId) : + SfxChildWindow(pParentWindow, nId), + 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(); + pDlgInterface = pFact->CreateSwFieldDlg(pB, this, _pParent->GetFrameWeld()); + SetController(pDlgInterface->GetController()); + 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 + { + pDlgInterface->ReInitDlg(); + } + + return bRet; +} + +void SwFieldDlgWrapper::ShowReferencePage() +{ + 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(); + pDlgInterface = pFact->CreateSwFieldDlg(pB, this, _pParent->GetFrameWeld()); + + SetController(pDlgInterface->GetController()); + pDlgInterface->ActivateDatabasePage(); + pDlgInterface->StartExecuteAsync(nullptr); + pDlgInterface->Initialize( pInfo ); +} + +// re-init after doc activation +bool SwFieldDataOnlyDlgWrapper::ReInitDlg(SwDocShell *pDocSh) +{ + bool bRet = SwChildWinWrapper::ReInitDlg(pDocSh); + if (bRet) // update immediately, Doc switch + { + 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 000000000..96321fab7 --- /dev/null +++ b/sw/source/uibase/fldui/xfldui.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 = m_pWrtShell ? m_pWrtShell->GetDBManager() : + ::GetActiveView()->GetWrtShell().GetDBManager(); + + Reference< XConnection> xConnection = + pDBManager->RegisterConnection(rDBName); + + if( !xConnection.is() ) + return bNumeric; + + Reference xColsSupplier; + if(bIsTable) + { + Reference xTSupplier(xConnection, UNO_QUERY); + if(xTSupplier.is()) + { + Reference xTables = xTSupplier->getTables(); + OSL_ENSURE(xTables->hasByName(rTableQryName), "table not available anymore?"); + try + { + Any aTable = xTables->getByName(rTableQryName); + Reference xPropSet; + aTable >>= xPropSet; + xColsSupplier.set(xPropSet, UNO_QUERY); + } + catch (const Exception&) + { + } + } + } + else + { + Reference xQSupplier(xConnection, UNO_QUERY); + if(xQSupplier.is()) + { + Reference xQueries = xQSupplier->getQueries(); + OSL_ENSURE(xQueries->hasByName(rTableQryName), "table not available anymore?"); + try + { + Any aQuery = xQueries->getByName(rTableQryName); + Reference xPropSet; + aQuery >>= xPropSet; + xColsSupplier.set(xPropSet, UNO_QUERY); + } + catch (const Exception&) + { + } + } + } + + if(xColsSupplier.is()) + { + Reference xCols; + try + { + xCols = xColsSupplier->getColumns(); + } + catch (const Exception&) + { + OSL_FAIL("Exception in getColumns()"); + } + if(xCols.is() && xCols->hasByName(rFieldName)) + { + Any aCol = xCols->getByName(rFieldName); + Reference 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 000000000..8d458f016 --- /dev/null +++ b/sw/source/uibase/frmdlg/colex.cxx @@ -0,0 +1,607 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(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(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(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(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(pItem)->GetItemSet(); + const SfxBoolItem& rHeaderOn = + static_cast(rHeaderSet.Get( pPool->GetWhich( SID_ATTR_PAGE_ON ) ) ); + + if ( rHeaderOn.GetValue() ) + { + const SvxSizeItem& rSize = + static_cast(rHeaderSet.Get(pPool->GetWhich(SID_ATTR_PAGE_SIZE))); + + const SvxULSpaceItem& rUL = static_cast(rHeaderSet.Get( + pPool->GetWhich(SID_ATTR_ULSPACE))); + const SvxLRSpaceItem& rLR = static_cast(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); + SfxItemSet aTempSet(*rHeaderSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setHeaderFillAttributes( + std::make_shared( + aTempSet)); + } + } + else + SetHeader( false ); + } + + if( SfxItemState::SET == rSet.GetItemState( pPool->GetWhich( SID_ATTR_PAGE_FOOTERSET), + false, &pItem ) ) + { + const SfxItemSet& rFooterSet = static_cast(pItem)->GetItemSet(); + const SfxBoolItem& rFooterOn = rFooterSet.Get( SID_ATTR_PAGE_ON ); + + if ( rFooterOn.GetValue() ) + { + const SvxSizeItem& rSize = + static_cast(rFooterSet.Get( pPool->GetWhich( SID_ATTR_PAGE_SIZE ) )); + + const SvxULSpaceItem& rUL = static_cast(rFooterSet.Get( + pPool->GetWhich( SID_ATTR_ULSPACE ) )); + const SvxLRSpaceItem& rLR = static_cast(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); + SfxItemSet aTempSet(*rFooterSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setFooterFillAttributes( + std::make_shared( + aTempSet)); + } + } + else + SetFooter( false ); + } + + if(SfxItemState::SET == rSet.GetItemState(RES_BACKGROUND, false, &pItem)) + { + // create FillAttributes from SvxBrushItem + const SvxBrushItem& rItem = static_cast< const SvxBrushItem& >(*pItem); + SfxItemSet aTempSet(*rSet.GetPool(), svl::Items{}); + + setSvxBrushItemAsFillAttributesToTargetSet(rItem, aTempSet); + setPageFillAttributes( + std::make_shared( + aTempSet)); + } + + Invalidate(); +} + +void SwColExample::DrawPage(vcl::RenderContext& rRenderContext, const Point& rOrg, + const bool bSecond, const bool bEnabled) +{ + SwPageExample::DrawPage(rRenderContext, rOrg, bSecond, bEnabled); + if (!pColMgr) + return; + sal_uInt16 nColumnCount = pColMgr->GetCount(); + if (!nColumnCount) + return; + + long nL = GetLeft(); + 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( + rFieldColor)); + } + + // #97495# make sure that the automatic column width's are always equal + bool bAutoWidth = pColMgr->IsAutoWidth(); + sal_Int32 nAutoColWidth = 0; + if (bAutoWidth) + { + sal_Int32 nColumnWidthSum = 0; + for (sal_uInt16 i = 0; i < nColumnCount; ++i) + nColumnWidthSum += pColMgr->GetColWidth( i ); + nAutoColWidth = nColumnWidthSum / nColumnCount; + } + + for (sal_uInt16 i = 0; i < nColumnCount; ++i) + { + if (!bAutoWidth) + nAutoColWidth = 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() + pColMgr->GetGutterWidth(i) ); + else + aRect.SetTop( aRect.Bottom() + pColMgr->GetGutterWidth(i) ); + } + } + if (pColMgr->HasLine()) + { + Point aUp(rOrg.X() + nL, rOrg.Y() + GetTop()); + Point aDown(rOrg.X() + nL, + rOrg.Y() + GetSize().Height() - GetBottom() - GetFtHeight() - GetFtDist()); + + if (pColMgr->GetLineHeightPercent() != 100) + { + long nLength = !m_bVertical ? aDown.Y() - aUp.Y() : aDown.X() - aUp.X(); + nLength -= nLength * pColMgr->GetLineHeightPercent() / 100; + switch (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 = pColMgr->GetGutterWidth(i); + int nDist = 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, static_cast(m_aFrameSize.Width())); +} + +void SwColumnOnlyExample::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + rRenderContext.Push(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::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? + 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); + 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(); + 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]; + long nWish = pCol->GetWishWidth(); + nWish *= nFrameWidth; + nWish /= nWishSum; + pCol->SetWishWidth(static_cast(nWish)); + long nLeft = pCol->GetLeft(); + nLeft *= nFrameWidth; + nLeft /= nWishSum; + pCol->SetLeft(static_cast(nLeft)); + long nRight = pCol->GetRight(); + nRight *= nFrameWidth; + nRight /= nWishSum; + pCol->SetRight(static_cast(nRight)); + } + // #97495# make sure that the automatic column width's are always equal + if(nColCount && m_aCols.IsOrtho()) + { + 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(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 (!pGridItem || !pGridItem->GetGridType()) + return; + + //paint the grid now + Color aLineColor = pGridItem->GetColor(); + if (aLineColor == COL_AUTO) + { + aLineColor = rRenderContext.GetFillColor(); + aLineColor.Invert(); + } + rRenderContext.SetLineColor(aLineColor); + long nL = GetLeft(); + 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 = pGridItem->GetBaseHeight() * 3; + sal_Int32 nRubyHeight = 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 > pGridItem->GetLines()) + nLines = pGridItem->GetLines(); + + // determine start position + if (m_bVertical) + { + sal_Int16 nXStart = static_cast(aRect.GetWidth() / 2 - nLineHeight * nLines /2); + aRubyRect.Move(nXStart, 0); + aCharRect.Move(nXStart, 0); + } + else + { + sal_Int16 nYStart = static_cast(aRect.GetHeight() / 2 - nLineHeight * nLines /2); + aRubyRect.Move(0, nYStart); + aCharRect.Move(0, nYStart); + } + + if (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 = 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 ) +{ + pGridItem.reset(); + //get the grid information + if (SfxItemState::DEFAULT <= rSet.GetItemState(RES_TEXTGRID)) + 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 000000000..8dda357ee --- /dev/null +++ b/sw/source/uibase/frmdlg/colmgr.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 + +#include + +#include +#include +#include + +#include +#include +#include + +// 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) +{ + aFormatCol.Init(nCount, nGutterWidth, nWidth); + aFormatCol.SetWishWidth(nWidth); + aFormatCol.SetGutterWidth(nGutterWidth, nWidth); +} + +sal_uInt16 SwColMgr::GetGutterWidth( sal_uInt16 nPos ) const +{ + sal_uInt16 nRet; + if(nPos == USHRT_MAX ) + nRet = GetCount() > 1 ? aFormatCol.GetGutterWidth() : DEF_GUTTER_WIDTH; + else + { + OSL_ENSURE(nPos < GetCount() - 1, "column overindexed" ); + const SwColumns& rCols = 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) + aFormatCol.SetGutterWidth(nGutterWidth, nWidth); + else + { + OSL_ENSURE(nPos < GetCount() - 1, "column overindexed" ); + SwColumns& rCols = 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(aFormatCol.GetLineHeight()); +} +void SwColMgr::SetLineHeightPercent(short nPercent) +{ + OSL_ENSURE(nPercent <= 100, "line height may be at most 100%"); + aFormatCol.SetLineHeight(static_cast(nPercent)); +} + +// column width +sal_uInt16 SwColMgr::GetColWidth(sal_uInt16 nIdx) const +{ + OSL_ENSURE(nIdx < GetCount(), "Column array overindexed."); + return aFormatCol.CalcPrtColWidth(nIdx, nWidth); +} + +void SwColMgr::SetColWidth(sal_uInt16 nIdx, sal_uInt16 nWd) +{ + OSL_ENSURE(nIdx < GetCount(), "Column array overindexed."); + aFormatCol.GetColumns()[nIdx].SetWishWidth(nWd); + +} + +// newly set size +void SwColMgr::SetActualWidth(sal_uInt16 nW) +{ + nWidth = nW; + ::FitToActualSize(aFormatCol, nW); +} + +// ctor +SwColMgr::SwColMgr(const SfxItemSet& rSet) : + aFormatCol(rSet.Get(RES_COL)) +{ + nWidth = static_cast(rSet.Get(RES_FRM_SIZE).GetWidth()); + if (nWidth < MINLAY) + nWidth = USHRT_MAX; + const SvxLRSpaceItem &rLR = rSet.Get(RES_LR_SPACE); + nWidth = nWidth - static_cast(rLR.GetLeft()); + nWidth = nWidth - static_cast(rLR.GetRight()); + ::FitToActualSize(aFormatCol, nWidth); +} + +SwColMgr::~SwColMgr() +{ +} + +void SwColMgr::SetLineWidthAndColor(SvxBorderLineStyle eStyle, sal_uLong nLWidth, const Color& rCol) +{ + aFormatCol.SetLineStyle(eStyle); + aFormatCol.SetLineWidth(nLWidth); + 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 000000000..926a949e2 --- /dev/null +++ b/sw/source/uibase/frmdlg/frmmgr.cxx @@ -0,0 +1,613 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +static sal_uInt16 aFrameMgrRange[] = { + 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, + 0}; + +// determine frame attributes via Shell +SwFlyFrameAttrMgr::SwFlyFrameAttrMgr( bool bNew, SwWrtShell* pSh, Frmmgr_Type nType, const SvGlobalName* pName ) : + m_aSet( static_cast(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 )); + 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. + m_aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_CHAR)); + } + } + } + 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, const SfxItemSet &rSet ) : + m_aSet( rSet ), + 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_() +{ + const SfxPoolItem* pItem = nullptr; + + if (m_aSet.GetItemState(FN_SET_FRM_NAME, false, &pItem) == SfxItemState::SET) + m_pOwnSh->SetFlyName(static_cast(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() ) + { + //JP 6.8.2001: set never an invalid anchor into the core. + const SfxPoolItem *pGItem, *pItem; + if( SfxItemState::SET == m_aSet.GetItemState( RES_ANCHOR, false, &pItem )) + { + SfxItemSet aGetSet( *m_aSet.GetPool(), svl::Items{} ); + if( m_pOwnSh->GetFlyFrameAttr( aGetSet ) && 1 == aGetSet.Count() && + SfxItemState::SET == aGetSet.GetItemState( RES_ANCHOR, false, &pGItem ) + && static_cast(pGItem)->GetAnchorId() == + static_cast(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, nPhyPageNum ) ); + 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 SwPosition* 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()); + 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 + 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( long nLeft, 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( long nTop, 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(sal_uInt16 nOld, sal_uInt16 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(), long(MINFLY)), std::max(rSize.Height(), long(MINFLY)))); + m_aSet.Put( aSize ); +} + +void SwFlyFrameAttrMgr::SetAttrSet(const SfxItemSet& rSet) +{ + m_aSet.ClearItem(); + m_aSet.Put( rSet ); +} + +/* 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 000000000..283b5a016 --- /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 +#include +#include +#include + +#include +#include +#include + +// 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/DashedLine.hxx b/sw/source/uibase/inc/DashedLine.hxx new file mode 100644 index 000000000..0492be67e --- /dev/null +++ b/sw/source/uibase/inc/DashedLine.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +/** Class for displaying a dashed line in the Writer GUI. + */ +class SwDashedLine : public FixedLine +{ + Color& (*m_pColorFn)(); + +public: + SwDashedLine( vcl::Window* pParent, Color& ( *pColorFn )() ); + 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 000000000..11ae445fe --- /dev/null +++ b/sw/source/uibase/inc/DateFormFieldDialog.hxx @@ -0,0 +1,58 @@ +/* -*- 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 +#include "numfmtlb.hxx" + +class SvNumberFormatter; +class SwDoc; + +namespace sw +{ +namespace mark +{ +class IDateFieldmark; +} +} // namespace sw + +/// Dialog to specify the properties of date form field +namespace sw +{ +class DateFormFieldDialog : public weld::GenericDialogController +{ +private: + sw::mark::IDateFieldmark* m_pDateField; + SvNumberFormatter* m_pNumberFormatter; + + std::unique_ptr m_xFormatLB; + + void Apply(); + void InitControls(); + +public: + DateFormFieldDialog(weld::Widget* pParent, sw::mark::IDateFieldmark* pDateField, SwDoc* pDoc); + 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 000000000..59510d37b --- /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 + +class SwDropDownField; +class SwField; +class SwWrtShell; + +// Dialog to edit drop down field selection +namespace sw +{ +class DropDownFieldDialog : public weld::GenericDialogController +{ + SwWrtShell &m_rSh; + SwDropDownField* m_pDropField; + + weld::Button* m_pPressedButton; + std::unique_ptr m_xListItemsLB; + std::unique_ptr m_xOKPB; + std::unique_ptr m_xPrevPB; + std::unique_ptr m_xNextPB; + std::unique_ptr 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 000000000..ae1e1b51d --- /dev/null +++ b/sw/source/uibase/inc/DropDownFormFieldDialog.hxx @@ -0,0 +1,68 @@ +/* -*- 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 + +namespace sw +{ +namespace mark +{ +class IFieldmark; +} +} // namespace sw + +/// Dialog to specify the properties of drop-down form field +namespace sw +{ +class DropDownFormFieldDialog : public weld::GenericDialogController +{ +private: + mark::IFieldmark* m_pDropDownField; + bool m_bListHasChanged; + + std::unique_ptr m_xListItemEntry; + std::unique_ptr m_xListAddButton; + + std::unique_ptr m_xListItemsTreeView; + + std::unique_ptr m_xListRemoveButton; + std::unique_ptr m_xListUpButton; + std::unique_ptr 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 000000000..bf2ff6239 --- /dev/null +++ b/sw/source/uibase/inc/FrameControl.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/. + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROL_HXX + +#include + +#include "edtwin.hxx" + +class SwEditWin; +class SwPageFrame; +class SwFrame; +class Point; + +/// Abstract interface to be implemented by writer FrameControls +class 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; +}; + +class SwFrameControl final +{ + VclPtr mxWindow; + ISwFrameControl *mpIFace; +public: + SwFrameControl( const VclPtr &pWindow ); + ~SwFrameControl(); + + vcl::Window* GetWindow() { return mxWindow.get(); } + + 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 MenuButton, public ISwFrameControl +{ + VclPtr m_pEditWin; + const SwFrame* m_pFrame; + +protected: + virtual ~SwFrameMenuButtonBase() override { disposeOnce(); } + virtual void dispose() override; + +public: + SwFrameMenuButtonBase( SwEditWin* pEditWin, const SwFrame* pFrame ); + + virtual const SwFrame* GetFrame() override { return m_pFrame; } + virtual SwEditWin* GetEditWin() override { return m_pEditWin; } + const SwPageFrame* GetPageFrame() const; +}; + +#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 000000000..66685bd8b --- /dev/null +++ b/sw/source/uibase/inc/FrameControlsManager.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/. + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROLSMANAGER_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_FRAMECONTROLSMANAGER_HXX + +#include "FrameControl.hxx" + +#include + +#include +#include + +class SwPageFrame; +class SwEditWin; + +typedef std::shared_ptr< SwFrameControl > SwFrameControlPtr; + +typedef std::map SwFrameControlPtrMap; + +/** A container for the Header/Footer, or PageBreak controls. +*/ +class SwFrameControlsManager +{ + private: + VclPtr 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() ); +}; + +#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 000000000..dc1cee8cc --- /dev/null +++ b/sw/source/uibase/inc/HeaderFooterWin.hxx @@ -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/. + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_HEADERFOOTERWIN_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_HEADERFOOTERWIN_HXX + +#include "edtwin.hxx" +#include "FrameControl.hxx" +#include +#include +#include + +/** + * 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 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 SwHeaderFooterWin : public SwFrameMenuButtonBase +{ + VclBuilder m_aBuilder; + OUString m_sLabel; + bool m_bIsHeader; + VclPtr m_pPopupMenu; + VclPtr m_pLine; + 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, long nXLineStart, long nXLineEnd ); + + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual void Select( ) override; + + virtual void ShowAll( bool bShow ) override; + virtual bool Contains( const Point &rDocPt ) const override; + + bool IsHeader() const { return m_bIsHeader; }; + bool IsEmptyHeaderFooter( ) const; + + void ExecuteCommand(const OString &rIdent); + + void SetReadonly( bool bReadonly ) override; + +private: + DECL_LINK( FadeHandler, Timer *, void ); +}; + +#endif + +/* 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 000000000..982c81e15 --- /dev/null +++ b/sw/source/uibase/inc/PageBreakWin.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/. + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_PAGEBREAKWIN_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_PAGEBREAKWIN_HXX + +#include "edtwin.hxx" +#include "FrameControl.hxx" +#include +#include +#include + +class Menu; +class SwPageFrame; + +/** 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 SwPageBreakWin : public SwFrameMenuButtonBase +{ + VclBuilder m_aBuilder; + VclPtr m_pPopupMenu; + VclPtr m_pLine; + 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; + + std::optional m_xMousePt; + +public: + SwPageBreakWin( SwEditWin* pEditWin, const SwFrame *pFrame ); + virtual ~SwPageBreakWin() override; + virtual void dispose() override; + + virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle& rRect ) override; + virtual void Select( ) override; + virtual void MouseMove( const MouseEvent& rMEvt ) override; + virtual void Activate( ) override; + + void UpdatePosition(const std::optional& xEvtPt = std::optional()); + + virtual void ShowAll( bool bShow ) override; + virtual bool Contains( const Point &rDocPt ) const override; + + void SetReadonly( bool bReadonly ) override; + + void Fade( bool bFadeIn ); + +private: + /// Hide the button (used when the popup menu is closed by clicking outside) + DECL_LINK( HideHandler, Menu *, bool ); + DECL_LINK( FadeHandler, Timer *, void ); +}; + +#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 000000000..a6becb92b --- /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 + +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 000000000..82cd29204 --- /dev/null +++ b/sw/source/uibase/inc/SwSpellDialogChildWindow.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_SWSPELLDIALOGCHILDWINDOW_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SWSPELLDIALOGCHILDWINDOW_HXX + +#include +#include + +class SwWrtShell; +struct SpellState; +class SwSpellDialogChildWindow + : public svx::SpellDialogChildWindow +{ + bool m_bIsGrammarCheckingOn; + std::unique_ptr 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); + +protected: + 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 000000000..e9e036b5f --- /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 +#include +#include +#include +#include +#include +#include +#include + +namespace com::sun::star::io { class XInputStream; } + +class SwXFilterOptions : public ::cppu::WeakImplHelper< + css::beans::XPropertyAccess, + css::ui::dialogs::XExecutableDialog, + css::document::XImporter, + css::document::XExporter, + css::lang::XInitialization, + css::lang::XServiceInfo > +{ + OUString sFilterOptions; + + css::uno::Reference< css::io::XInputStream > xInputStream; + css::uno::Reference< css::lang::XComponent > xModel; + css::uno::Reference< css::awt::XWindow > 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& 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 000000000..701c824b8 --- /dev/null +++ b/sw/source/uibase/inc/UnfloatTableButton.hxx @@ -0,0 +1,46 @@ +/* -*- 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 : public SwFrameMenuButtonBase +{ + OUString m_sLabel; + +public: + UnfloatTableButton(SwEditWin* pEditWin, const SwFrame* pFrame); + virtual ~UnfloatTableButton() override; + + void SetOffset(Point aTopRightPixel); + + virtual void MouseButtonDown(const MouseEvent& rMEvt) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + + virtual void ShowAll(bool bShow) override; + virtual bool Contains(const Point& rDocPt) const override; + + virtual void SetReadonly(bool bReadonly) override; +}; + +#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 000000000..6d6f6ba60 --- /dev/null +++ b/sw/source/uibase/inc/abstract.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_ABSTRACT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_ABSTRACT_HXX + +#include + +class SwInsertAbstractDlg : public SfxDialogController +{ + std::unique_ptr m_xLevelNF; + std::unique_ptr m_xParaNF; + +public: + SwInsertAbstractDlg(weld::Window* pParent); + virtual ~SwInsertAbstractDlg() override; + + sal_uInt8 GetLevel() const; + sal_uInt8 GetPara() const; +}; + +#endif + +/* 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 000000000..feb839afd --- /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 + +class SwAddrDlg : 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 000000000..1dbf4208e --- /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 +#include +#include +#include + +class SwView; +class SwAnnotationShell: public SfxShell +{ + SwView& 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 000000000..330159551 --- /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 +#include +#include +#include + +class SwAsciiOptions; +class SvStream; +class SwDocShell; + +class SwAsciiFilterDlg : public SfxDialogController +{ + bool m_bSaveLineStatus; + OUString m_sExtraData; + + std::unique_ptr m_xCharSetLB; + std::unique_ptr m_xFontFT; + std::unique_ptr m_xFontLB; + std::unique_ptr m_xLanguageFT; + std::unique_ptr m_xLanguageLB; + std::unique_ptr m_xCRLF_RB; + std::unique_ptr m_xCR_RB; + std::unique_ptr m_xLF_RB; + std::unique_ptr m_xIncludeBOM_CB; + + DECL_LINK(CharSetSelHdl, weld::ComboBox&, void); + DECL_LINK(LineEndHdl, weld::ToggleButton&, 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 000000000..a5f41e4d9 --- /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 +#include +#include +#include +#include +#include +#include +#include + +#include "wrtsh.hxx" +#include + +class AutoFormatPreview : 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; + long mnLabelColumnWidth; + long mnDataColumnWidth1; + long mnDataColumnWidth2; + 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 mxNumFormat; + + uno::Reference 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 000000000..f40f2c7d1 --- /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 +#include + +enum class SelectionType : sal_Int32; + +class SwToolbarConfigItem : public utl::ConfigItem +{ + sal_Int32 aTbxIdArray[5]; + + static css::uno::Sequence 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 000000000..b4426137f --- /dev/null +++ b/sw/source/uibase/inc/basesh.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BASESH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_BASESH_HXX + +#include + +#include +#include +#include + +#include +#include + +class SwWrtShell; +class SwView; +class SfxItemSet; +class SwCursorShell; + +struct DBTextStruct_Impl; +class SW_DLLPUBLIC SwBaseShell: public SfxShell +{ + SwView &rView; + + // DragMode + static FlyMode eFrameMode; + + // Bug 75078 - if in GetState the async call of GetGraphic returns + // synch, the set the state directly into the itemset + SfxItemSet* pGetStateSet; + + // Update-Timer for graphic + std::set aGrfUpdateSlots; + + DECL_LINK( GraphicArrivedHdl, SwCursorShell&, void ); + +protected: + SwWrtShell& GetShell(); + SwWrtShell* GetShellPtr(); + + SwView& GetView() { return rView; } + void SetGetStateSet( SfxItemSet* p ) { pGetStateSet = p; } + bool AddGrfUpdateSlot( sal_uInt16 nSlot ){ return aGrfUpdateSlots.insert( nSlot ).second; } + + DECL_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 ) { eFrameMode = eMode; } + static FlyMode GetFrameMode() { return eFrameMode; } +}; + +#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 000000000..abf64aa65 --- /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: 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 000000000..46d9544b7 --- /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 +#include +#include + +// extended page for graphics +class BmpWindow : public weld::CustomWidgetController +{ +private: + Graphic aGraphic; + BitmapEx aBmp; + + bool bHorz : 1; + bool bVert : 1; + bool 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) { bVert = bMirror; Invalidate(); } + void MirrorHorz(bool bMirror) { 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 000000000..a69f020d6 --- /dev/null +++ b/sw/source/uibase/inc/bookctrl.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_BOOKCTRL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_BOOKCTRL_HXX + +#include +#include + +class SwBookmarkControl : public SfxStatusBarControl +{ + virtual void Command( const CommandEvent& rCEvt ) override; + +public: + virtual void StateChanged( 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; + +private: + OUString sPageNumber; +}; + +#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 000000000..3a8ee1506 --- /dev/null +++ b/sw/source/uibase/inc/bookmark.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_BOOKMARK_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_BOOKMARK_HXX + +#include +#include +#include +#include "condedit.hxx" + +class SwWrtShell; +class SfxRequest; + +class BookmarkTable +{ + std::unique_ptr m_xControl; + std::unique_ptr GetRowByBookmarkName(const OUString& sName); +public: + BookmarkTable(std::unique_ptr xControl); + void InsertBookmark(sw::mark::IMark* pMark); + void 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 get_selected() const; + void clear() { m_xControl->clear(); } + void remove(const weld::TreeIter& rIter) { m_xControl->remove(rIter); } + void select(const weld::TreeIter& rIter) { m_xControl->select(rIter); } + void remove_selection() { m_xControl->remove_selection(); } + 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& func) { m_xControl->selected_foreach(func); } + + void connect_changed(const Link& rLink) { m_xControl->connect_changed(rLink); } + void connect_row_activated(const Link& rLink) { m_xControl->connect_row_activated(rLink); } + void connect_column_clicked(const Link& rLink) { m_xControl->connect_column_clicked(rLink); } + 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 const OUString aForbiddenChars; + static const char cSeparator; +}; + +class SwInsertBookmarkDlg : public SfxDialogController +{ + SwWrtShell& rSh; + SfxRequest& rReq; + std::vector> aTableBookmarks; + sal_Int32 m_nLastBookmarksCount; + bool m_bSorted; + bool m_bAreProtected; + + std::unique_ptr m_xEditBox; + std::unique_ptr m_xInsertBtn; + std::unique_ptr m_xDeleteBtn; + std::unique_ptr m_xGotoBtn; + std::unique_ptr m_xRenameBtn; + std::unique_ptr m_xHideCB; + std::unique_ptr m_xConditionFT; + std::unique_ptr m_xConditionED; + std::unique_ptr m_xBookmarksBox; + std::unique_ptr m_xForbiddenChars; + + DECL_LINK(ModifyHdl, weld::Entry&, void); + DECL_LINK(InsertHdl, weld::Button&, void); + DECL_LINK(DeleteHdl, 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::ToggleButton&, void); + + // 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(); + +public: + SwInsertBookmarkDlg(weld::Window* pParent, SwWrtShell& rSh, SfxRequest& rReq); + virtual ~SwInsertBookmarkDlg() override; +}; + +#endif + +/* 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 000000000..9c07ce2b5 --- /dev/null +++ b/sw/source/uibase/inc/break.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_BREAK_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_BREAK_HXX + +#include +#include + +class SwWrtShell; + +class SwBreakDlg : public weld::GenericDialogController +{ + std::unique_ptr m_xLineBtn; + std::unique_ptr m_xColumnBtn; + std::unique_ptr m_xPageBtn; + std::unique_ptr m_xPageCollText; + std::unique_ptr m_xPageCollBox; + std::unique_ptr m_xPageNumBox; + std::unique_ptr m_xPageNumEdit; + std::unique_ptr m_xOkBtn; + + SwWrtShell &rSh; + OUString m_aTemplate; + sal_uInt16 nKind; + ::std::optional oPgNum; + + bool bHtmlMode; + + DECL_LINK(ToggleHdl, weld::ToggleButton&, void); + DECL_LINK(ChangeHdl, weld::ComboBox&, void); + DECL_LINK(PageNumHdl, weld::ToggleButton&, void); + DECL_LINK(PageNumModifyHdl, weld::SpinButton&, void); + DECL_LINK(OkHdl, weld::Button&, void); + + void CheckEnable(); + +public: + SwBreakDlg(weld::Window *pParent, SwWrtShell &rSh); + virtual short run() override; + const OUString& GetTemplateName() const { return m_aTemplate; } + sal_uInt16 GetKind() const { return nKind; } + const ::std::optional& GetPageNumber() const { return oPgNum; } +}; + +#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 000000000..d762091b1 --- /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 +#include +#include +#include + +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 000000000..bf50b8f10 --- /dev/null +++ b/sw/source/uibase/inc/cfgitems.hxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include + +class SwModule; +#ifdef DBG_UTIL +class SwTestTabPage; +#endif +class SwAddPrinterTabPage; +class SfxPrinter; +class SwViewShell; +class SwViewOption; +class SwContentOptPage; +class SwShdwCursorOptionsTabPage; +enum class SwFillMode; + +// OS 12.01.95 +// Item for settings dialog - document view +class SW_DLLPUBLIC SwDocDisplayItem : public SfxPoolItem +{ + friend class SwShdwCursorOptionsTabPage; + friend class SwModule; + + bool bParagraphEnd :1; + bool bTab :1; + bool bSpace :1; + bool bNonbreakingSpace :1; + bool bSoftHyphen :1; + bool bCharHiddenText :1; + bool bBookmarks :1; + bool bManualBreak :1; + +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 : 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_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 : 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 : public SfxPoolItem +{ + SwFillMode eMode; + bool 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 eMode; } + bool IsOn() const { return bOn; } + + void SetMode( SwFillMode eM ) { eMode = eM; } + void SetOn( bool bFlag ) { bOn = bFlag; } +}; + +#ifdef DBG_UTIL + +// Item for settings dialog - test settings +class SW_DLLPUBLIC SwTestItem : 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 000000000..a56144bd9 --- /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 +#include "dbtree.hxx" + +class SwFieldMgr; +class SwView; +class SwWrtShell; +struct SwDBData; + +// exchange database at fields +class SwChangeDBDlg : public SfxDialogController +{ + SwWrtShell *pSh; + + std::unique_ptr m_xUsedDBTLB; + std::unique_ptr m_xAvailDBTLB; + std::unique_ptr m_xAddDBPB; + std::unique_ptr m_xDocDBNameFT; + std::unique_ptr 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 Insert(const OUString& 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 000000000..d258053ae --- /dev/null +++ b/sw/source/uibase/inc/chartins.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX + +#include +#include + +namespace vcl { class Window; } + +Point SwGetChartDialogPos( const vcl::Window *pParentWin, const Size& rDialogSize, const tools::Rectangle& rLogicChart ); + +class SwInsertChart +{ +public: + SwInsertChart( const Link& 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 000000000..b6f5b41ab --- /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 +#include + +class SwDocShell; + +class SAL_DLLPUBLIC_RTTI SwChildWinWrapper : public SfxChildWindow +{ + Timer m_aUpdateTimer; + SwDocShell* m_pDocSh; + + DECL_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 000000000..09138b5cc --- /dev/null +++ b/sw/source/uibase/inc/chrdlg.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_CHRDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CHRDLG_HXX + +#include +#include "chrdlgmodes.hxx" + +class SwView; +class SvxMacroItem; + +class SwCharDlg : 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 OString& rId, SfxTabPage &rPage) override; +}; + +class SwCharURLPage : public SfxTabPage +{ + std::unique_ptr pINetItem; + bool bModified; + + std::unique_ptr m_xURLED; + std::unique_ptr m_xTextFT; + std::unique_ptr m_xTextED; + std::unique_ptr m_xNameED; + std::unique_ptr m_xTargetFrameLB; + std::unique_ptr m_xURLPB; + std::unique_ptr m_xEventPB; + std::unique_ptr m_xVisitedLB; + std::unique_ptr m_xNotVisitedLB; + std::unique_ptr 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 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 000000000..cddb6a9c2 --- /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 000000000..e95cc5c62 --- /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 + +#include + +#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 000000000..41f7e4143 --- /dev/null +++ b/sw/source/uibase/inc/colex.hxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include + +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 : public SwPageExample +{ + std::unique_ptr pGridItem; +protected: + 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 : public SwPageExample +{ + SwColMgr* pColMgr; + + using SwPageExample::UpdateExample; + +protected: + virtual void DrawPage(vcl::RenderContext& rRenderContext, + const Point& rPoint, + const bool bSecond, + const bool bEnabled) override; + +public: + SwColExample() + : pColMgr(nullptr) + { + } + + void UpdateExample( const SfxItemSet& rSet, SwColMgr* pMgr ) + { + pColMgr = pMgr; + SwPageExample::UpdateExample(rSet); + } +}; + +class SW_DLLPUBLIC SwColumnOnlyExample : public weld::CustomWidgetController +{ +private: + Size m_aWinSize; + + Size m_aFrameSize; + SwFormatCol m_aCols; + +protected: + 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 000000000..928e1dcfa --- /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 +#include + +#include + +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 aFormatCol; } + + void SetActualWidth(sal_uInt16 nW); + sal_uInt16 GetActualSize() const { return nWidth; } + +private: + SwFormatCol aFormatCol; + sal_uInt16 nWidth; +}; + +inline sal_uInt16 SwColMgr::GetCount() const +{ + return aFormatCol.GetNumCols(); +} + +inline SvxBorderLineStyle SwColMgr::GetLineStyle() const +{ + return aFormatCol.GetLineStyle(); +} +inline sal_uLong SwColMgr::GetLineWidth() const +{ + return aFormatCol.GetLineWidth(); +} + +inline const Color& SwColMgr::GetLineColor() const +{ + return aFormatCol.GetLineColor(); +} + +inline SwColLineAdj SwColMgr::GetAdjust() const +{ + return aFormatCol.GetLineAdj(); +} + +inline void SwColMgr::SetAdjust(SwColLineAdj eAdj) +{ + aFormatCol.SetLineAdj(eAdj); +} +inline bool SwColMgr::IsAutoWidth() const +{ + return aFormatCol.IsOrtho(); +} +inline void SwColMgr::SetAutoWidth(bool bOn, sal_uInt16 nGutterWidth) +{ + aFormatCol.SetOrtho(bOn, nGutterWidth, nWidth); +} + +inline void SwColMgr::NoCols() +{ + 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 000000000..1b799c1c2 --- /dev/null +++ b/sw/source/uibase/inc/column.hxx @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_COLUMN_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_COLUMN_HXX + +#include +#include +#include +#include +#include +#include +#include "colex.hxx" +#include "prcntfld.hxx" + +const int nMaxCols = 99; +class SwColMgr; +class SwWrtShell; +class SwColumnPage; + +class SwColumnDlg : public SfxDialogController +{ + SwWrtShell& m_rWrtShell; + std::unique_ptr m_xTabPage; + std::unique_ptr m_pPageSet; + std::unique_ptr m_pSectionSet; + std::unique_ptr m_pSelectionSet; + SfxItemSet* m_pFrameSet; + + long m_nOldSelection; + long m_nSelectionWidth; + long m_nPageWidth; + + bool m_bPageChanged : 1; + bool m_bSectionChanged : 1; + bool m_bSelSectionChanged : 1; + bool m_bFrameChanged : 1; + + std::unique_ptr m_xContentArea; + std::unique_ptr 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 : 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 : public SfxTabPage +{ + std::unique_ptr m_xColMgr; + + sal_uInt16 m_nFirstVis; + sal_uInt16 m_nCols; + long m_nColWidth[nMaxCols]; + long m_nColDist[nMaxCols]; + SwPercentField* m_pModifiedField; + + std::map 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 m_xCLNrEdt; + std::unique_ptr m_xBalanceColsCB; + std::unique_ptr m_xBtnBack; + std::unique_ptr m_xLbl1; + std::unique_ptr m_xLbl2; + std::unique_ptr m_xLbl3; + std::unique_ptr m_xBtnNext; + std::unique_ptr m_xAutoWidthBox; + std::unique_ptr m_xLineTypeLbl; + std::unique_ptr m_xLineWidthLbl; + std::unique_ptr m_xLineWidthEdit; + std::unique_ptr m_xLineColorLbl; + std::unique_ptr m_xLineHeightLbl; + std::unique_ptr m_xLineHeightEdit; + std::unique_ptr m_xLinePosLbl; + std::unique_ptr m_xLinePosDLB; + std::unique_ptr m_xTextDirectionFT; + std::unique_ptr m_xTextDirectionLB; + std::unique_ptr m_xLineColorDLB; + std::unique_ptr m_xLineTypeDLB; + std::unique_ptr m_xEd1; + std::unique_ptr m_xEd2; + std::unique_ptr m_xEd3; + std::unique_ptr m_xDistEd1; + std::unique_ptr m_xDistEd2; + std::unique_ptr m_xDefaultVS; + // Example + std::unique_ptr m_xPgeExampleWN; + std::unique_ptr m_xFrameExampleWN; + + std::unique_ptr m_xApplyToFT; + std::unique_ptr m_xApplyToLB; + + // Handler + DECL_LINK(ColModify, weld::SpinButton&, void); + void ColModify(const weld::SpinButton*); + DECL_LINK(GapModify, weld::MetricSpinButton&, void); + DECL_LINK(EdModify, weld::MetricSpinButton&, void); + DECL_LINK(AutoWidthHdl, weld::ToggleButton&, 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 sal_uInt16 aPageRg[]; + +public: + SwColumnPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwColumnPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* GetRanges() { return aPageRg; } + + virtual bool FillItemSet(SfxItemSet *rSet) override; + virtual void Reset(const SfxItemSet *rSet) override; + + void SetFrameMode(bool bMod); + void SetPageWidth(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(); } +}; + +#endif + +/* 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 000000000..b1b31ec03 --- /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 : 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 000000000..4d67a00dd --- /dev/null +++ b/sw/source/uibase/inc/concustomshape.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_CONCUSTOMSHAPE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CONCUSTOMSHAPE_HXX + +#include +#include "drawbase.hxx" + +class SdrObject; +class SfxRequest; + +// draw rectangle +class ConstCustomShape : public SwDrawBase +{ + + OUString 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; + + // #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 000000000..974fecf95 --- /dev/null +++ b/sw/source/uibase/inc/condedit.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_CONDEDIT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CONDEDIT_HXX + +#include +#include +#include + +class ConditionEdit; + +class SW_DLLPUBLIC ConditionEditDropTarget : 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 m_xControl; + ConditionEditDropTarget m_aDropTargetHelper; + bool bBrackets, bEnableDrop; + +public: + ConditionEdit(std::unique_ptr 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); } + bool get_sensitive() const { return m_xControl->get_sensitive(); } + 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& 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; } + + void ShowBrackets(bool bShow) { bBrackets = bShow; } + bool GetBrackets() const { return bBrackets; } + void SetDropEnable(bool bFlag) { bEnableDrop = bFlag; } + bool GetDropEnable() const { return 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 000000000..65e01caf9 --- /dev/null +++ b/sw/source/uibase/inc/conform.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_CONFORM_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CONFORM_HXX + +#include "drawbase.hxx" + +class ConstFormControl : public SwDrawBase +{ +public: + ConstFormControl(SwWrtShell* pSh, SwEditWin* pWin, SwView* pView); + + // Mouse- & Key-Events + virtual bool MouseButtonDown(const MouseEvent& rMEvt) override; + + virtual void Activate(const sal_uInt16 nSlotId) override; // activate function + virtual void CreateDefaultObject() override; +}; + +#endif + +/* 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 000000000..d1fad7db3 --- /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 : 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 000000000..878d99c80 --- /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 : public SwDrawBase +{ + bool bMarquee; + bool 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 000000000..414db7068 --- /dev/null +++ b/sw/source/uibase/inc/content.hxx @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include "swcont.hxx" + +#include + +class SwWrtShell; +class SwContentArr; +class SwContentType; +class SwFormatField; +class SwTextINetFormat; +class SwTOXBase; +class SwRangeRedline; + +// helper classes + +class SwOutlineContent : public SwContent +{ + SwOutlineNodes::size_type nOutlinePos; + sal_uInt8 nOutlineLevel; + bool bIsMoveable; + public: + SwOutlineContent( const SwContentType* pCnt, + const OUString& rName, + SwOutlineNodes::size_type nArrPos, + sal_uInt8 nLevel, + bool bMove, + long nYPos) : + SwContent(pCnt, rName, nYPos), + nOutlinePos(nArrPos), nOutlineLevel(nLevel), bIsMoveable(bMove) {} + + SwOutlineNodes::size_type GetOutlinePos() const {return nOutlinePos;} + sal_uInt8 GetOutlineLevel() const {return nOutlineLevel;} + bool IsMoveable() const {return bIsMoveable;}; +}; + +class SwRegionContent : public SwContent +{ + + sal_uInt8 nRegionLevel; + + public: + SwRegionContent( const SwContentType* pCnt, + const OUString& rName, + sal_uInt8 nLevel, + long nYPos) : + SwContent(pCnt, rName, nYPos), + nRegionLevel(nLevel){} + sal_uInt8 GetRegionLevel() const {return nRegionLevel;} +}; + +class SwURLFieldContent : public SwContent +{ + OUString sURL; + const SwTextINetFormat* pINetAttr; + +public: + SwURLFieldContent( const SwContentType* pCnt, + const OUString& rName, + const OUString& rURL, + const SwTextINetFormat* pAttr, + long nYPos ) + : SwContent( pCnt, rName, nYPos ), sURL( rURL ), pINetAttr( pAttr ) + {} + + virtual bool IsProtect() const override; + const OUString& GetURL() const { return sURL; } + const SwTextINetFormat* GetINetAttr() const { return pINetAttr; } +}; + +class SwPostItContent : public SwContent +{ + const SwFormatField* pField; +public: + SwPostItContent( const SwContentType* pCnt, + const OUString& rName, + const SwFormatField* pFormatField, + long nYPos ) + : SwContent(pCnt, rName, nYPos) + , pField(pFormatField) + {} + + const SwFormatField* GetPostIt() const { return pField; } + virtual bool IsProtect() const override; +}; + +class SwGraphicContent : public SwContent +{ + OUString sLink; +public: + SwGraphicContent(const SwContentType* pCnt, const OUString& rName, const OUString& rLink, long nYPos) + : SwContent( pCnt, rName, nYPos ), sLink( rLink ) + {} + virtual ~SwGraphicContent() override; + + const OUString& GetLink() const {return sLink;} +}; + +class SwTOXBaseContent : public SwContent +{ + const SwTOXBase* pBase; +public: + SwTOXBaseContent(const SwContentType* pCnt, const OUString& rName, long nYPos, const SwTOXBase& rBase) + : SwContent( pCnt, rName, nYPos ), pBase(&rBase) + {} + virtual ~SwTOXBaseContent() override; + + const SwTOXBase* GetTOXBase() const {return 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 : public SwTypeNumber +{ + SwWrtShell* m_pWrtShell; + std::unique_ptr + 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? +protected: + static OUString RemoveNewline(const OUString&); +public: + SwContentType(SwWrtShell* pParent, ContentTypeId nType, sal_uInt8 nLevel ); + virtual ~SwContentType() override; + + void Init(bool* pbInvalidateWindow = nullptr); + + /** Fill the List of contents */ + void FillMemberList(bool* pbLevelChanged = 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(); + } + + 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/conttree.hxx b/sw/source/uibase/inc/conttree.hxx new file mode 100644 index 000000000..59df0d51c --- /dev/null +++ b/sw/source/uibase/inc/conttree.hxx @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include "swcont.hxx" + +#include +#include + +#include +#include + +class SwWrtShell; +class SwContentType; +class SwNavigationPI; +class SwNavigationConfig; +class Menu; +class ToolBox; +class SwGlblDocContents; +class SwGlblDocContent; +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 : is_typed_flags {}; +} + +class SwContentTree; + +class SwContentTreeDropTarget : 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 m_xTreeView; + SwContentTreeDropTarget m_aDropTargetHelper; + VclPtr m_xDialog; + OUString m_sSpace; + AutoTimer m_aUpdTimer; + + o3tl::enumarray> m_aActiveContentArr; + o3tl::enumarray> m_aHiddenContentArr; + OUString m_aContextStrings[CONTEXT_COUNT + 1]; + OUString m_sInvisible; + + SwWrtShell* m_pHiddenShell; // dropped Doc + SwWrtShell* m_pActiveShell; // the active or a const. open view + SwNavigationConfig* m_pConfig; + + std::map< void*, bool > mOutLineNodeMap; + + sal_Int32 m_nActiveBlock; + sal_Int32 m_nHiddenBlock; + size_t m_nEntryCount; + ContentTypeId m_nRootType; + ContentTypeId m_nLastSelType; + sal_uInt8 m_nOutlineLevel; + + sal_uInt32 m_nOutlineTracking = 1; + + 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> m_aDndOutlinesSelected; + + bool m_bIsInPromoteDemote = false; + + /** + * Before any data will be deleted, the last active entry has to be found. + * After this the UserData will be deleted + */ + void FindActiveTypeAndRemoveUserData(); + + void insert(const weld::TreeIter* pParent, const OUString& rStr, const OUString& rId, + const OUString* pExpanderName, 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 OString& rSelectedPopupEntry); + + void DeleteOutlineSelections(); + + size_t GetEntryCount() const; + + size_t GetChildCount(const weld::TreeIter& rParent) const; + + std::unique_ptr GetEntryAtAbsPos(size_t nAbsPos) const; + + void Expand(const weld::TreeIter& rParent, std::vector>* 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(SelectHdl, weld::TreeView&, void); + DECL_LINK(FocusHdl, 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); + +public: + SwContentTree(std::unique_ptr 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; + + sal_uInt8 GetOutlineLevel()const {return m_nOutlineLevel;} + void SetOutlineLevel(sal_uInt8 nSet); + + /** Execute commands of the Navigator */ + void ExecCommand(const OString& 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(); + + // return true if it has any children + bool RequestingChildren(const weld::TreeIter& rParent); + + 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(); + } + + OUString get_selected_text() const + { + return m_xTreeView->get_selected_text(); + } + + int count_selected_rows() const + { + return m_xTreeView->count_selected_rows(); + } + + 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 : 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 +{ +private: + std::unique_ptr m_xTreeView; + SwGlobalTreeDropTarget m_aDropTargetHelper; + VclPtr m_xDialog; + AutoTimer m_aUpdateTimer; + OUString m_aContextStrings[GLOBAL_CONTEXT_COUNT]; + + SwWrtShell* m_pActiveShell; + std::unique_ptr m_pSwGlblDocContents; // array with sorted content + + std::unique_ptr m_pDocContent; + std::unique_ptr m_pDocInserter; + + static const SfxObjectShell* 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) {pShowShell = pSet;} + DECL_STATIC_LINK(SwGlobalTree, ShowFrameHdl, void*, void); + +public: + SwGlobalTree(std::unique_ptr 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(); + } + + int count_selected_rows() const + { + return m_xTreeView->count_selected_rows(); + } + + void set_selection_mode(SelectionMode eMode) + { + m_xTreeView->set_selection_mode(eMode); + } + + weld::TreeView& get_widget() + { + return *m_xTreeView; + } + + void MoveSelectionTo(weld::TreeIter* pDropTarget); + + void TbxMenuHdl(const OString& rCommand, weld::Menu& rMenu); + void InsertRegion( const SwGlblDocContent* pCont, + const OUString* pFileName = nullptr ); + void EditContent(const SwGlblDocContent* pCont ); + + void ShowTree(); + void HideTree(); + + void ExecCommand(const OString& rCmd); + + void Display(bool bOnlyUpdateUserData = false); + + bool Update(bool bHard); + + void ExecuteContextMenuAction(const OString& rSelectedPopupEntry); + + const SwWrtShell* GetActiveWrtShell() const {return m_pActiveShell;} +}; + +#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 000000000..08a831b0b --- /dev/null +++ b/sw/source/uibase/inc/convert.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_CONVERT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_CONVERT_HXX + +#include +#include + +class VclContainer; +class SwTableAutoFormat; +class SwView; +class SwWrtShell; +struct SwInsertTableOptions; + +class SwConvertTableDlg : public SfxDialogController +{ + std::unique_ptr m_xTabBtn; + std::unique_ptr m_xSemiBtn; + std::unique_ptr m_xParaBtn; + std::unique_ptr m_xOtherBtn; + std::unique_ptr m_xOtherEd; + std::unique_ptr m_xKeepColumn; + + std::unique_ptr m_xOptions; + + std::unique_ptr m_xHeaderCB; + std::unique_ptr m_xRepeatHeaderCB; + + std::unique_ptr m_xRepeatRows; + std::unique_ptr m_xRepeatHeaderNF; + + std::unique_ptr m_xDontSplitCB; + std::unique_ptr m_xAutoFormatBtn; + + std::unique_ptr mxTAutoFormat; + SwWrtShell* pShell; + + DECL_LINK(AutoFormatHdl, weld::Button&, void); + DECL_LINK(BtnHdl, weld::Button&, void); + DECL_LINK(CheckBoxHdl, weld::Button&, void); + DECL_LINK(ReapeatHeaderCheckBoxHdl, weld::Button&, 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 000000000..16fa1f063 --- /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 + +#include + +#include "wrtsh.hxx" +#include "optload.hxx" + +class SwFieldMgr; +class SwView; + +class SwCaptionDialog : public SfxDialogController +{ + OUString m_sNone; + TextFilterAutoConvert m_aTextFilter; + SwView &rView; // search per active, avoid View + std::unique_ptr pMgr; // pointer to save the include + + OUString sCharacterStyle; + bool bCopyAttributes; + bool bOrderNumberingFirst; //#i61007# order of captions + + css::uno::Reference< css::container::XNameAccess > xNameAccess; + + SwCaptionPreview m_aPreview; + std::unique_ptr m_xTextEdit; + std::unique_ptr m_xCategoryBox; + std::unique_ptr m_xFormatText; + std::unique_ptr m_xFormatBox; + //#i61007# order of captions + std::unique_ptr m_xNumberingSeparatorFT; + std::unique_ptr m_xNumberingSeparatorED; + std::unique_ptr m_xSepText; + std::unique_ptr m_xSepEdit; + std::unique_ptr m_xPosText; + std::unique_ptr m_xPosBox; + std::unique_ptr m_xOKButton; + std::unique_ptr m_xAutoCaptionButton; + std::unique_ptr m_xOptionButton; + std::unique_ptr 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); + + void Apply(); + + void ModifyHdl(); + void DrawSample(); + void ApplyCaptionOrder(); //#i61007# order of captions + + static OUString our_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 000000000..5a611f5d8 --- /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 +#include + +struct SwDBData; + +class SW_DLLPUBLIC SwDBConfig : public utl::ConfigItem +{ +private: + SAL_DLLPRIVATE static const css::uno::Sequence& GetPropertyNames(); + virtual void ImplCommit() override; + + std::unique_ptr pAdrImpl; + std::unique_ptr 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 000000000..0dc715d1c --- /dev/null +++ b/sw/source/uibase/inc/dbinsdlg.hxx @@ -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 . + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBINSDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_DBINSDLG_HXX + +#include +#include +#include +#include "numfmtlb.hxx" +#include +#include +#include +#include + +#include +#include + +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> DB_Columns; + +struct SwInsDBColumn +{ + OUString sColumn, sUsrNumFormat; + sal_Int32 nDBNumFormat; + sal_uInt32 nUsrNumFormat; + LanguageType eUsrNumFormatLng; + bool bHasFormat : 1; + bool bIsDBFormat : 1; + + SwInsDBColumn( const OUString& rStr ) + : sColumn( rStr ), + nDBNumFormat( 0 ), + nUsrNumFormat( 0 ), + eUsrNumFormatLng( LANGUAGE_SYSTEM ), + bHasFormat(false), + bIsDBFormat(true) + {} + + bool operator<( const SwInsDBColumn& rCmp ) const; +}; + +class SwInsDBColumns : public o3tl::sorted_vector, o3tl::less_uniqueptr_to > +{ +}; + +class SwInsertDBColAutoPilot : public SfxDialogController, public utl::ConfigItem +{ + SwInsDBColumns aDBColumns; + const SwDBData aDBData; + + OUString sNoTmpl; + + SwView* pView; + std::unique_ptr m_xTAutoFormat; + + std::unique_ptr pTableSet; + std::unique_ptr pRep; + sal_Int32 nGBFormatLen; + + std::unique_ptr m_xRbAsTable; + std::unique_ptr m_xRbAsField; + std::unique_ptr m_xRbAsText; + + std::unique_ptr m_xHeadFrame; + + std::unique_ptr m_xLbTableDbColumn; + std::unique_ptr m_xLbTextDbColumn; + + std::unique_ptr m_xFormatFrame; + std::unique_ptr m_xRbDbFormatFromDb; + std::unique_ptr m_xRbDbFormatFromUsr; + std::unique_ptr m_xLbDbFormatFromUsr; + + // Page Text/Field + std::unique_ptr m_xIbDbcolToEdit; + std::unique_ptr m_xEdDbText; + std::unique_ptr m_xFtDbParaColl; + std::unique_ptr m_xLbDbParaColl; + + // Page Table + std::unique_ptr m_xIbDbcolAllTo; + std::unique_ptr m_xIbDbcolOneTo; + std::unique_ptr m_xIbDbcolOneFrom; + std::unique_ptr m_xIbDbcolAllFrom; + std::unique_ptr m_xFtTableCol; + std::unique_ptr m_xLbTableCol; + std::unique_ptr m_xCbTableHeadon; + std::unique_ptr m_xRbHeadlColnms; + std::unique_ptr m_xRbHeadlEmpty; + std::unique_ptr m_xPbTableFormat; + std::unique_ptr m_xPbTableAutofmt; + + DECL_LINK( PageHdl, weld::Button&, void ); + DECL_LINK( AutoFormatHdl, weld::Button&, void ); + DECL_LINK( TableFormatHdl, weld::Button&, void ); + DECL_LINK( DBFormatHdl, weld::Button&, 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::Button&, 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 const & xColSupp, + const SwDBData& rData ); + + 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 000000000..e3c994d44 --- /dev/null +++ b/sw/source/uibase/inc/dbtree.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_DBTREE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_DBTREE_HXX + +#include +#include + +#include + +class SwDBTreeList_Impl; +class SwWrtShell; + +class SW_DLLPUBLIC SwDBTreeList +{ + bool bInitialized; + bool bShowColumns; + + rtl::Reference pImpl; + std::unique_ptr m_xTreeView; + + DECL_DLLPRIVATE_LINK(RequestingChildrenHdl, const weld::TreeIter&, bool); + SAL_DLLPRIVATE void InitTreeList(); + +public: + SwDBTreeList(std::unique_ptr xTreeView); + ~SwDBTreeList(); + + OUString GetDBName(OUString& rTableName, OUString& rColumnName, sal_Bool* pbIsTable = nullptr); + + void Select( const OUString& rDBName, const OUString& rTableName, + const OUString& rColumnName ); + + void ShowColumns(bool bShowCol); + + void SetWrtShell(SwWrtShell& rSh); + + void AddDataSource(const OUString& rSource); + + void connect_changed(const Link& rLink) { m_xTreeView->connect_changed(rLink); } + void connect_row_activated(const Link& rLink) { m_xTreeView->connect_row_activated(rLink); } + std::unique_ptr 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 000000000..38ace352a --- /dev/null +++ b/sw/source/uibase/inc/dbui.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DBUI_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_DBUI_HXX + +#include + +#include + +class PrintMonitor: public weld::GenericDialogController +{ +public: + std::unique_ptr m_xDocName; + std::unique_ptr m_xPrinter; + std::unique_ptr m_xPrintInfo; + + PrintMonitor(weld::Window *pParent); + virtual ~PrintMonitor() override; +}; + +class SW_DLLPUBLIC SaveMonitor : public weld::GenericDialogController +{ +public: + std::unique_ptr m_xDocName; + std::unique_ptr m_xPrinter; + std::unique_ptr m_xPrintInfo; + + SaveMonitor(weld::Window *pParent); + virtual ~SaveMonitor() override; +}; + +class CreateMonitor : 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 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 000000000..521e2114a --- /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 + +class SwWrtShell; + +class SwFootNoteOptionDlg : public SfxTabDialogController +{ + SwWrtShell &rSh; + + virtual void PageCreated(const OString& 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 000000000..56119d057 --- /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 +#include + +// 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 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 m_xPageNo; + std::unique_ptr m_xTableNo; + std::unique_ptr m_xGrfNo; + std::unique_ptr m_xOLENo; + std::unique_ptr m_xParaNo; + std::unique_ptr m_xWordNo; + std::unique_ptr m_xCharNo; + std::unique_ptr m_xCharExclSpacesNo; + std::unique_ptr m_xLineLbl; + std::unique_ptr m_xLineNo; + std::unique_ptr m_xUpdatePB; + + SwDocStat 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 000000000..6aeb4455a --- /dev/null +++ b/sw/source/uibase/inc/drawbase.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_DRAWBASE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_DRAWBASE_HXX + +#include +#include + +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 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(); + + // #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 000000000..b204a39d9 --- /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 + +class SwDrawBaseShell; + +class SwDrawShell: 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 000000000..9c8602d14 --- /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 000000000..2ff081427 --- /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 +#include +#include +#include +#include +#include + +class SwWrtShell; + +class SwDropCapsDlg : public SfxSingleTabDialogController +{ +public: + SwDropCapsDlg(weld::Window *pParent, const SfxItemSet &rSet); +}; + +class SwDropCapsPage; + +class SwDropCapsPict : public weld::CustomWidgetController +{ + SwDropCapsPage* mpPage; + OUString maText; + OUString maScriptText; + Color maBackColor; + Color maTextLineColor; + sal_uInt8 mnLines; + long mnTotLineH; + long mnLineH; + long mnTextH; + sal_uInt16 mnDistance; + VclPtr 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 maScriptChanges; + SvxFont maFont; + SvxFont maCJKFont; + SvxFont maCTLFont; + Size maTextSize; + css::uno::Reference< css::i18n::XBreakIterator > xBreak; + + virtual void Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle &rRect) override; + void CheckScript(); + Size CalcTextSize(); + inline void InitPrinter(); + void InitPrinter_(); + static void GetFontSettings( const SwDropCapsPage& _rPage, 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 : public SfxTabPage +{ +friend class SwDropCapsPict; + SwDropCapsPict m_aPict; + + bool bModified; + bool bFormat; + bool bHtmlMode; + + SwWrtShell &rSh; + + std::unique_ptr m_xDropCapsBox; + std::unique_ptr m_xWholeWordCB; + std::unique_ptr m_xSwitchText; + std::unique_ptr m_xDropCapsField; + std::unique_ptr m_xLinesText; + std::unique_ptr m_xLinesField; + std::unique_ptr m_xDistanceText; + std::unique_ptr m_xDistanceField; + std::unique_ptr m_xTextText; + std::unique_ptr m_xTextEdit; + std::unique_ptr m_xTemplateText; + std::unique_ptr m_xTemplateBox; + std::unique_ptr m_xPict; + + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + void FillSet( SfxItemSet &rSet ); + + void ModifyEntry(weld::Entry& rEdit); + + DECL_LINK(ClickHdl, weld::ToggleButton&, 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::ToggleButton&, void); + + static const sal_uInt16 aPageRg[]; + +public: + SwDropCapsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwDropCapsPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* GetRanges() { return aPageRg; } + + + virtual bool FillItemSet( SfxItemSet *rSet) override; + virtual void Reset (const SfxItemSet *rSet) override; + + void SetFormat(bool bSet){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 000000000..e75576dec --- /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 000000000..47a9fbd44 --- /dev/null +++ b/sw/source/uibase/inc/drwtxtsh.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_DRWTXTSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_DRWTXTSH_HXX + +#include +#include +#include + +class SdrView; +class SwView; +class SwWrtShell; + +class SwDrawTextShell: public SfxShell +{ + SwView &rView; + RotateTransliteration m_aRotateCase; + + SdrView *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 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 000000000..cac7e5ce4 --- /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 : 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 000000000..4416bc73c --- /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 + +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 000000000..3059ee609 --- /dev/null +++ b/sw/source/uibase/inc/edtwin.hxx @@ -0,0 +1,301 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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; + +// 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::Window, + public DropTargetHelper, public DragSourceHelper +{ + static QuickHelpData* m_pQuickHlpData; + + static long m_nDDStartPosX; + static long m_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 m_pApplyTempl; + std::unique_ptr m_pAnchorMarker; // for relocating the anchor + + std::unique_ptr m_pUserMarker; + SdrObject *m_pUserMarkerObj; + std::unique_ptr> m_pShadCursor; + std::optional 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 m_pFrameControlsManager; + + void LeaveArea(const Point &); + void JustifyAreaTimer(); + inline void EnterArea(); + + void RstMBDownFlags(); + + 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_LINK( TimerHandler, Timer *, void ); + void StartDDTimer(); + void StopDDTimer(SwWrtShell *, const Point &); + DECL_LINK( DDHandler, Timer *, void ); + + // timer for ANY-KeyInut question without a following KeyInputEvent + DECL_LINK( KeyInputFlushHandler, Timer *, void ); + + // timer for ApplyTemplates via mouse (in disguise Drag&Drop) + DECL_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; + + void ShowAutoCorrectQuickHelp(const OUString& rWord, SvxAutoCorrect& rACorr); + bool ShowAutoText(const std::vector& 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 long GetDDStartPosX() { return m_nDDStartPosX; } + static long GetDDStartPosY() { return m_nDDStartPosY; } + + static void InitStaticData(); + static void FinitStaticData(); + + //#i3370# remove quick help to prevent saving of autocorrection suggestions + void StopQuickHelp(); + + // #i42921# - add parameter + 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; + /// Same as MouseButtonDown(), but coordinates are in logic unit. + virtual void LogicMouseButtonDown(const MouseEvent& rMouseEvent) override; + /// Same as MouseButtonUp(), but coordinates are in logic unit. + virtual void LogicMouseButtonUp(const MouseEvent& rMouseEvent) override; + /// Same as MouseMove(), but coordinates are in logic unit. + virtual void LogicMouseMove(const MouseEvent& rMouseEvent) 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); + + virtual FactoryFunction GetUITestFactory() const override; +}; + +extern bool g_bFrameDrag; +extern bool g_bDDTimerStarted; +extern bool g_bFlushCharBuffer; +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 000000000..b63d6b0a5 --- /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 +#include +#include + +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 : 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 : public utl::ConfigItem +{ +private: + SwEnvItem m_aEnvItem; + + static css::uno::Sequence 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 000000000..7455d3579 --- /dev/null +++ b/sw/source/uibase/inc/envlop.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_ENVLOP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_ENVLOP_HXX + +#include +#include +#include +#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 : 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 : public SfxTabDialogController +{ +friend class SwEnvPage; +friend class SwEnvFormatPage; +friend class SwEnvPrtPage; +friend class SwEnvPreview; + + SwEnvItem aEnvItem; + SwWrtShell *pSh; + VclPtr pPrinter; + std::unique_ptr pAddresseeSet; + std::unique_ptr pSenderSet; + + std::unique_ptr m_xModify; + + virtual void PageCreated(const OString& 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 : public SfxTabPage +{ + SwEnvDlg* m_pDialog; + SwWrtShell* m_pSh; + OUString m_sActDBName; + + SwEnvPreview m_aPreview; + std::unique_ptr m_xAddrEdit; + std::unique_ptr m_xDatabaseLB; + std::unique_ptr m_xTableLB; + std::unique_ptr m_xDBFieldLB; + std::unique_ptr m_xInsertBT; + std::unique_ptr m_xSenderBox; + std::unique_ptr m_xSenderEdit; + std::unique_ptr m_xPreview; + + DECL_LINK(DatabaseHdl, weld::ComboBox&, void); + DECL_LINK(FieldHdl, weld::Button&, void); + DECL_LINK(SenderHdl, weld::Button&, 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 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 000000000..9f512ea3f --- /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 + +#include + +class SwView; +class SwWrtShell; +class SwFieldMgr; + +class SwFieldEditDlg : public SfxSingleTabDialogController +{ + SwWrtShell* pSh; + std::unique_ptr m_xPrevBT; + std::unique_ptr m_xNextBT; + std::unique_ptr 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 000000000..9a701e2a4 --- /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 +#include +#include +#include +#include +#include +#include + +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 vcl { class Window; } +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::unique_ptr m_pAnnotationRange; + + SwInsertField_Data(SwFieldTypesEnum nType, sal_uInt16 nSub, const OUString& rPar1, const OUString& rPar2, + sal_uInt32 nFormatId, SwWrtShell* pShell = nullptr, sal_Unicode cSep = ' ', bool bIsAutoLanguage = true) : + m_nTypeId(nType), + m_nSubType(nSub), + m_sPar1(rPar1), + m_sPar2(rPar2), + 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; + + sal_uInt32 m_nCurFormat; + bool m_bEvalExp; + + SAL_DLLPRIVATE LanguageType GetCurrLanguage() const; + + css::uno::Reference m_xNumberingInfo; + SAL_DLLPRIVATE css::uno::Reference const & GetNumberingInfo()const; + +public: + explicit SwFieldMgr(SwWrtShell* pSh = nullptr); + ~SwFieldMgr(); + + void SetWrtShell( SwWrtShell* pShell ) + { m_pWrtShell = pShell; } + + // insert field using TypeID (TYP_ ...) + bool InsertField( const SwInsertField_Data& rData ); + + // change the current field directly + void UpdateCurField(sal_uInt32 nFormat, + const OUString& rPar1, + const OUString& rPar2, + std::unique_ptr _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( const OUString& 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 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& 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 000000000..159881ed1 --- /dev/null +++ b/sw/source/uibase/inc/fldtdlg.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FLDTDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_FLDTDLG_HXX +#include + +class SfxBindings; +class SfxTabPage; +class SwChildWinWrapper; +struct SfxChildWinInfo; + +class SwFieldDlg : public SfxTabDialogController +{ + SwChildWinWrapper* m_pChildWin; + SfxBindings* m_pBindings; + bool m_bHtmlMode; + bool m_bDataBaseMode; + bool m_bClosing; + + virtual SfxItemSet* CreateInputItemSet(const OString& rId) override; + virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override; + + void ReInitTabPage(const OString& 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() 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 000000000..6532ff7db --- /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 + +#include + +#include "chldwrap.hxx" +class AbstractSwFieldDlg; + +class SwFieldDlgWrapper : public SwChildWinWrapper +{ + ScopedVclPtr 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 : public SwChildWinWrapper +{ + ScopedVclPtr 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 000000000..388f16d81 --- /dev/null +++ b/sw/source/uibase/inc/fontcfg.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FONTCFG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_FONTCFG_HXX + +#include +#include +#include +#include + +#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_CJK_DEFAULT 210 +#define FONTSIZE_OUTLINE 280 + +class SW_DLLPUBLIC SwStdFontConfig : public utl::ConfigItem +{ + OUString sDefaultFonts[DEF_FONT_COUNT]; + sal_Int32 nDefaultFontHeight[DEF_FONT_COUNT]; + + SAL_DLLPRIVATE static css::uno::Sequence const & GetPropertyNames(); + + void ChangeString(sal_uInt16 nFontType, const OUString& rSet) + { + if(sDefaultFonts[nFontType] != rSet) + { + SetModified(); + 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 sDefaultFonts[FONT_STANDARD + FONT_PER_GROUP * nFontGroup];} + const OUString& GetFontOutline(sal_uInt8 nFontGroup) const {return sDefaultFonts[FONT_OUTLINE + FONT_PER_GROUP * nFontGroup];} + const OUString& GetFontList (sal_uInt8 nFontGroup) const {return sDefaultFonts[FONT_LIST + FONT_PER_GROUP * nFontGroup];} + const OUString& GetFontCaption(sal_uInt8 nFontGroup) const {return sDefaultFonts[FONT_CAPTION + FONT_PER_GROUP * nFontGroup];} + const OUString& GetFontIndex (sal_uInt8 nFontGroup) const {return sDefaultFonts[FONT_INDEX + FONT_PER_GROUP * nFontGroup];} + + const OUString& GetFontFor(sal_uInt16 nFontType) const {return 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 000000000..262ecfc68 --- /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 + +#include + +#include "wrtsh.hxx" +#include +#include + +/** 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 m_pItemSet_TextAttr; + /** automatic/named paragraph attribute set + * (it can be character attribute applied to the paragraph) */ + std::unique_ptr m_pItemSet_ParAttr; + + /** table attribute set */ + std::unique_ptr 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 000000000..e3c079a22 --- /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 +#include + +class SwWrtShell; + +// frame dialog +class SwFrameDlg : public SfxTabDialogController +{ + bool m_bFormat; + bool m_bNew; + const SfxItemSet& m_rSet; + OUString m_sDlgType; + SwWrtShell* m_pWrtShell; + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; + +public: + SwFrameDlg(SfxViewFrame const *pFrame, weld::Window* pParent, + const SfxItemSet& rCoreSet, + bool bNewFrame, + const OUString& sResType, + bool bFormat, + const OString& sDefPage = OString(), + 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 000000000..8cd1ee303 --- /dev/null +++ b/sw/source/uibase/inc/frmmgr.hxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include + +class SwWrtShell; +struct SvxSwFrameValidation; +struct SwPosition; + +class SwFormatCol; +class SvGlobalName; + +const SwTwips DFLT_WIDTH = MM50 * 4; +const SwTwips DFLT_HEIGHT = MM50; + +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, const SfxItemSet &rSet ); + + 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(sal_uInt16 nOld, sal_uInt16 nNew, const Size& rUnrotatedSize); + + // space to content + void SetLRSpace( long nLeft, + long nRight ); + void SetULSpace( long nTop, + 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 SwPosition* 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); + + 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; + + long CalcWidthBorder() { return CalcLeftSpace()+CalcRightSpace(); } + 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 000000000..6aba31a44 --- /dev/null +++ b/sw/source/uibase/inc/frmpage.hxx @@ -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 . + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_FRMPAGE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_FRMPAGE_HXX + +#include +#include +#include +#include +#include +#include "bmpwin.hxx" +#include "prcntfld.hxx" + +namespace sfx2{class FileDialogHelper;} +class SwWrtShell; +struct FrameMap; +// OD 12.11.2003 #i22341# +struct SwPosition; + +// frame dialog +class SwFramePage: 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 SwPosition* 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 m_xWidthFT; + std::unique_ptr m_xWidthAutoFT; + std::unique_ptr m_xRelWidthCB; + std::unique_ptr m_xRelWidthRelationLB; + std::unique_ptr m_xAutoWidthCB; + + std::unique_ptr m_xHeightFT; + std::unique_ptr m_xHeightAutoFT; + std::unique_ptr m_xRelHeightCB; + std::unique_ptr m_xRelHeightRelationLB; + std::unique_ptr m_xAutoHeightCB; + + std::unique_ptr m_xFixedRatioCB; + std::unique_ptr m_xRealSizeBT; + + // anchor + std::unique_ptr m_xAnchorFrame; + std::unique_ptr m_xAnchorAtPageRB; + std::unique_ptr m_xAnchorAtParaRB; + std::unique_ptr m_xAnchorAtCharRB; + std::unique_ptr m_xAnchorAsCharRB; + std::unique_ptr m_xAnchorAtFrameRB; + + // position + std::unique_ptr m_xHorizontalFT; + std::unique_ptr m_xHorizontalDLB; + std::unique_ptr m_xAtHorzPosFT; + std::unique_ptr m_xAtHorzPosED; + std::unique_ptr m_xHoriRelationFT; + std::unique_ptr m_xHoriRelationLB; + + std::unique_ptr m_xMirrorPagesCB; + + std::unique_ptr m_xVerticalFT; + std::unique_ptr m_xVerticalDLB; + std::unique_ptr m_xAtVertPosFT; + std::unique_ptr m_xAtVertPosED; + std::unique_ptr m_xVertRelationFT; + std::unique_ptr m_xVertRelationLB; + // #i18732# - check box for new option 'FollowTextFlow' + std::unique_ptr m_xFollowTextFlowCB; + + // example + std::unique_ptr m_xExampleWN; + + std::unique_ptr m_xWidthED; + std::unique_ptr m_xHeightED; + + virtual void ActivatePage(const SfxItemSet& rSet) override; + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + + DECL_LINK(RangeModifyClickHdl, weld::ToggleButton&, void); + void RangeModifyHdl(); + DECL_LINK(AnchorTypeHdl, weld::ToggleButton&, 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, + long nX, long nY); + + DECL_LINK(RealSizeHdl, weld::Button&, void); + DECL_LINK(RelSizeClickHdl, weld::ToggleButton&, void); + DECL_LINK(MirrorHdl, weld::ToggleButton&, void); + + DECL_LINK(AutoWidthClickHdl, weld::ToggleButton&, void); + DECL_LINK(AutoHeightClickHdl, weld::ToggleButton&, 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 sal_uInt16 aPageRg[]; + +public: + SwFramePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwFramePage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* GetRanges() { return 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 ); +}; + +class SwGrfExtPage : public SfxTabPage +{ + OUString aFilterName; + OUString aGrfName, aNewGrfName; + + std::unique_ptr<::sfx2::FileDialogHelper> m_xGrfDlg; + + bool m_bHtmlMode; + + // mirror + BmpWindow m_aBmpWin; + std::unique_ptr m_xMirror; + std::unique_ptr m_xMirrorVertBox; + std::unique_ptr m_xMirrorHorzBox; + std::unique_ptr m_xAllPagesRB; + std::unique_ptr m_xLeftPagesRB; + std::unique_ptr m_xRightPagesRB; + + std::unique_ptr m_xConnectED; + std::unique_ptr m_xBrowseBT; + std::unique_ptr m_xLinkFrame; + + // RotGrfFlyFrame: Need Angle and RotateControls now + std::unique_ptr m_xFlAngle; + std::unique_ptr m_xNfAngle; + std::unique_ptr m_xCtlAngle; + std::unique_ptr m_xCtlAngleWin; + std::unique_ptr m_xBmpWin; + + + // handler for mirroring + DECL_LINK(MirrorHdl, weld::ToggleButton&, 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 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 : public SfxTabPage +{ + // hyperlink + std::unique_ptr m_xURLED; + std::unique_ptr m_xSearchPB; + std::unique_ptr m_xNameED; + std::unique_ptr m_xFrameCB; + + // image map + std::unique_ptr m_xServerCB; + std::unique_ptr 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 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 : public SfxTabPage +{ + SwWrtShell* m_pWrtSh; + + OUString m_sDlgType; + bool m_bHtmlMode; + bool m_bFormat; + bool m_bNew; + + std::unique_ptr m_xNameFrame; + std::unique_ptr m_xNameFT; + std::unique_ptr m_xNameED; + std::unique_ptr m_xAltNameFT; + std::unique_ptr m_xAltNameED; + std::unique_ptr m_xDescriptionFT; + std::unique_ptr m_xDescriptionED; + std::unique_ptr m_xPrevFT; + std::unique_ptr m_xPrevLB; + std::unique_ptr m_xNextFT; + std::unique_ptr m_xNextLB; + + std::unique_ptr m_xProtectFrame; + std::unique_ptr m_xProtectContentCB; + std::unique_ptr m_xProtectFrameCB; + std::unique_ptr m_xProtectSizeCB; + + std::unique_ptr m_xContentAlignFrame; + std::unique_ptr m_xVertAlignLB; + + std::unique_ptr m_xPropertiesFrame; + std::unique_ptr m_xEditInReadonlyCB; + std::unique_ptr m_xPrintFrameCB; + std::unique_ptr m_xTextFlowFT; + std::unique_ptr m_xTextFlowLB; + + DECL_LINK(EditModifyHdl, weld::Entry&, void); + DECL_LINK(ChainModifyHdl, weld::ComboBox&, void); + + static const sal_uInt16 aAddPgRg[]; + +public: + SwFrameAddPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwFrameAddPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* GetRanges() { return 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 000000000..3bb36497b --- /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 000000000..8617d791c --- /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 000000000..b5ba48a97 --- /dev/null +++ b/sw/source/uibase/inc/glosbib.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_GLOSBIB_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSBIB_HXX + +#include +#include +#include + +#include + +class SwGlossaryHdl; + +struct GlosBibUserData +{ + OUString sPath; + OUString sGroupName; + OUString sGroupTitle; +}; + +class SwGlossaryGroupDlg final : public SfxDialogController +{ + std::vector m_RemovedArr; + std::vector m_InsertedArr; + std::vector m_RenamedArr; + + weld::Window* m_pParent; + SwGlossaryHdl* pGlosHdl; + + OUString sCreatedGroup; + + std::unique_ptr m_xNameED; + std::unique_ptr m_xPathLB; + std::unique_ptr m_xGroupTLB; + + std::unique_ptr m_xNewPB; + std::unique_ptr m_xDelPB; + std::unique_ptr 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 const& rPathArr, + SwGlossaryHdl *pGlosHdl); + virtual short run() override; + virtual ~SwGlossaryGroupDlg() override; + + const OUString& GetCreatedGroupName() const {return 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 000000000..14b4be59e --- /dev/null +++ b/sw/source/uibase/inc/glosdoc.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_GLOSDOC_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSDOC_HXX + +#include +#include + +class SwTextBlocks; +class SwDocShell; + +#ifndef SW_DECL_SWDOCSHELL_DEFINED +#define SW_DECL_SWDOCSHELL_DEFINED +#include +typedef tools::SvRef SwDocShellRef; +#endif +#include + +#include +#include + +typedef std::vector< css::uno::WeakReference< css::text::XAutoTextGroup > > UnoAutoTextGroups; +typedef std::vector< css::uno::WeakReference< css::text::XAutoTextEntry > > UnoAutoTextEntries; + +#define GLOS_DELIM u'*' + +class SW_DLLPUBLIC SwGlossaries +{ + UnoAutoTextGroups m_aGlossaryGroups; + UnoAutoTextEntries m_aGlossaryEntries; + + OUString m_aPath; + std::vector m_aInvalidPaths; + std::vector m_PathArr; + std::vector m_GlosArr; + bool m_bError; + + SAL_DLLPRIVATE std::unique_ptr GetGlosDoc(const OUString &rName, bool bCreate = true) const; + SAL_DLLPRIVATE std::vector & 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 _bCreate is , 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( + const OUString& _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 _bCreate is , 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 + GetGroupDoc(const OUString &rName, + bool bCreate = false); + static OUString GetDefName(); + static OUString GetExtension(); + + OUString GetCompleteGroupName( const OUString& GroupName ); + + bool NewGroupDoc(OUString &rGroupName, const OUString& rTitle); + bool RenameGroupDoc(const OUString& sOldGroup, OUString& sNewGroup, const OUString& rNewTitle); + bool DelGroupDoc(const OUString &); + 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 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 000000000..dd876c3a6 --- /dev/null +++ b/sw/source/uibase/inc/gloshdl.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include + +class SwWrtShell; +class SwTextBlocks; +class SvxMacro; +class SwGlossaries; +class SfxViewFrame; + +class SW_DLLPUBLIC SwGlossaryHdl +{ + + SwGlossaries& rStatGlossaries; + OUString aCurGrp; + SfxViewFrame* pViewFrame; + SwWrtShell* pWrtShell; + std::unique_ptr + pCurGrp; + + SAL_DLLPRIVATE bool Expand(weld::Window* pParent, const OUString& rShortName, + SwGlossaries* pGlossaries, + std::unique_ptr 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(const OUString &rName); + OUString GetGlossaryShortName(sal_uInt16); + + bool Rename( const OUString& rOldShortName, const OUString& rNewShortName, + const OUString& rNewName); + 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* pViewFrame, 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 000000000..3da5d8861 --- /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 +#include +#include + +#include + +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 : public AutoTimer +{ + std::vector> aGroupArr; + OUString sPath; + bool bFilled; + + AutoTextGroup* FindGroup(const OUString& rGroupName); + static void FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGloss); + +public: + SwGlossaryList(); + virtual ~SwGlossaryList() override; + + void HasLongName(const std::vector& rBeginCandidates, + std::vector>& rLongNames); + bool GetShortName(const OUString& 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 000000000..7f0dab689 --- /dev/null +++ b/sw/source/uibase/inc/glossary.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_GLOSSARY_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_GLOSSARY_HXX + +#include +#include +#include + +#include + +#include +#include + +struct GroupUserData; +class SwGlossaryHdl; +class SwNewGlosNameDlg; +class SwWrtShell; +class SfxViewFrame; +class PopupMenu; +class Menu; +class SwOneExampleFrame; + +const short RET_EDIT = 100; + +class SwGlossaryDlg : 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> m_xGroupData; + + std::unique_ptr m_xInsertTipCB; + std::unique_ptr m_xNameED; + std::unique_ptr m_xShortNameLbl; + TextFilter m_aNoSpaceFilter; + std::unique_ptr m_xShortNameEdit; + std::unique_ptr m_xCategoryBox; + std::unique_ptr m_xFileRelCB; + std::unique_ptr m_xNetRelCB; + std::unique_ptr m_xInsertBtn; + std::unique_ptr m_xEditBtn; + std::unique_ptr m_xBibBtn; + std::unique_ptr m_xPathBtn; + std::unique_ptr m_xExampleFrame; + std::unique_ptr m_xExampleFrameWin; + + 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 OString&, void ); + DECL_LINK( EnableHdl, weld::ToggleButton&, void ); + DECL_LINK( BibHdl, weld::Button&, void ); + DECL_LINK( InsertHdl, weld::Button&, void ); + DECL_LINK( PathHdl, weld::Button&, void ); + DECL_LINK( CheckBoxHdl, weld::ToggleButton&, void ); + DECL_LINK( PreviewLoadedHdl, SwOneExampleFrame&, void ); + DECL_LINK( KeyInputHdl, const KeyEvent&, bool ); + DECL_LINK( TextFilterHdl, OUString&, bool ); + + void Apply(); + void Init(); + std::unique_ptr DoesBlockExist(const OUString& sBlock, const OUString& 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(SfxViewFrame const * pViewFrame, 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 000000000..04fb73302 --- /dev/null +++ b/sw/source/uibase/inc/glshell.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_GLSHELL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_GLSHELL_HXX +#include + +class SwGlosDocShell : public SwDocShell +{ + OUString aLongName; + OUString aShortName; + OUString aGroupName; + +protected: + 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 ) + { aLongName = rLongName; } + void SetShortName( const OUString& rShortName ) + { aShortName = rShortName; } + void SetGroupName( const OUString& rGroupName ) + { aGroupName = rGroupName; } +}; + +class SwWebGlosDocShell : public SwWebDocShell +{ + OUString aLongName; + OUString aShortName; + OUString aGroupName; + +protected: + 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 ) + { aLongName = rLongName; } + void SetShortName( const OUString& rShortName ) + { aShortName = rShortName; } + void SetGroupName( const OUString& rGroupName ) + { 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 000000000..357fabf42 --- /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 +#include + +#include "basesh.hxx" +#include + +#include + +class SwGrfShell: public SwBaseShell +{ + class SwExternalToolEdit; + std::vector> 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 000000000..9b2d26d12 --- /dev/null +++ b/sw/source/uibase/inc/hyp.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_HYP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_HYP_HXX + +#include +#include +#include + +class SwView; + +class SW_DLLPUBLIC SwHyphWrapper : public SvxSpellWrapper { +private: + SwView* pView; + sal_uInt16 nPageCount; // page count for progress view + sal_uInt16 nPageStart; // 1st checked page + bool bInSelection : 1; // separating selected text + bool bAutomatic : 1; // insert separators without further inquiry + bool bInfoBox : 1; // display info-box when ending + +protected: + 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 000000000..e180ebed2 --- /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 + +#include + +class SwWrtShell; + +class SwInsertIdxMarkWrapper final : public SfxChildWindow +{ + ScopedVclPtr 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 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 000000000..8852a8800 --- /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 +#include +#include + +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 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 000000000..5f2b145ea --- /dev/null +++ b/sw/source/uibase/inc/initui.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_INITUI_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_INITUI_HXX + +#include +#include + +/* + * Forward Declarations + */ +class SwThesaurus; + +/* + * Extern Definitions + */ +extern SwThesaurus* pThes; + +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 000000000..f1dfc725d --- /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 + +class SwInputField; +class SwSetExpField; +class SwUserFieldType; +class SwField; +class SwWrtShell; +class SwFieldMgr; + +// insert fields +class SwFieldInputDlg : public weld::GenericDialogController +{ + void Apply(); + + SwWrtShell& rSh; + SwInputField* pInpField; + SwSetExpField* pSetField; + SwUserFieldType* pUsrType; + + weld::Button* m_pPressedButton; + std::unique_ptr m_xLabelED; + std::unique_ptr m_xEditED; + std::unique_ptr m_xPrevBT; + std::unique_ptr m_xNextBT; + std::unique_ptr 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 000000000..6698e1924 --- /dev/null +++ b/sw/source/uibase/inc/inputwin.hxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include + +class SwFieldMgr; +class SwWrtShell; +class SwView; +class SfxDispatcher; + +class InputEdit final : public InterimItemWindow +{ +private: + std::unique_ptr 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")) + { + 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(const OUString& rSel, const OUString& rTableName); + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + 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) + { + m_xWidget->replace_selection(rText); + } + + void select_region(int nStartPos, int nEndPos) + { + m_xWidget->select_region(nStartPos, nEndPos); + } + + void connect_changed(const Link& rLink) + { + m_xWidget->connect_changed(rLink); + } + + virtual ~InputEdit() override + { + disposeOnce(); + } +}; + + +class PosEdit final : public InterimItemWindow +{ +private: + std::unique_ptr 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")) + { + m_xWidget->connect_key_press(LINK(this, PosEdit, KeyInputHdl)); + SetSizePixel(m_xWidget->get_preferred_size()); + } + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + 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 mxPos; + VclPtr mxEdit; + std::unique_ptr pMgr; + SwWrtShell* pWrtShell; + SwView* pView; + OUString aCurrentTableName, sOldFormula; + + bool bFirst : 1; // initialisations at first call + bool bIsTable : 1; + bool 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; + DECL_LINK( MenuHdl, Menu *, bool ); + 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 pView;} +}; + +class SwInputChild : public SfxChildWindow +{ + SfxDispatcher* 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(GetWindow())->SetFormula( rFormula ); } + const SwView* GetView() const + { return static_cast(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 000000000..6ea4cc339 --- /dev/null +++ b/sw/source/uibase/inc/insfnote.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_INSFNOTE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_INSFNOTE_HXX + +#include + +class SwWrtShell; + +class VclFrame; + +class SwInsFootNoteDlg: 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 m_xNumberFrame; + std::unique_ptr m_xNumberAutoBtn; + std::unique_ptr m_xNumberCharBtn; + std::unique_ptr m_xNumberCharEdit; + std::unique_ptr m_xNumberExtChar; + + // everything for the selection footnote/endnote + std::unique_ptr m_xFootnoteBtn; + std::unique_ptr m_xEndNoteBtn; + + std::unique_ptr m_xOkBtn; + std::unique_ptr m_xPrevBT; + std::unique_ptr m_xNextBT; + + DECL_LINK(NumberCharHdl, weld::Button&, void); + DECL_LINK(NumberEditHdl, weld::Entry&, void); + DECL_LINK(NumberAutoBtnHdl, weld::Button&, 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 000000000..aa36dc655 --- /dev/null +++ b/sw/source/uibase/inc/instable.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_INSTABLE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_INSTABLE_HXX + +#include +#include +#include +#include +#include + +#include "wrtsh.hxx" +#include "autoformatpreview.hxx" +#include +#include +#include + +class SwInsTableDlg : public SfxDialogController +{ + TextFilter m_aTextFilter; + + SwWrtShell* pShell; + SwTableAutoFormatTable* pTableTable; + SwTableAutoFormat* pTAutoFormat; + + sal_uInt8 lbIndex; + sal_uInt8 tbIndex; + sal_uInt8 minTableIndexInLb; + sal_uInt8 maxTableIndexInLb; + sal_Int64 nEnteredValRepeatHeaderNF; + + AutoFormatPreview m_aWndPreview; + + std::unique_ptr m_xNameEdit; + std::unique_ptr m_xColNF; + std::unique_ptr m_xRowNF; + std::unique_ptr m_xHeaderCB; + std::unique_ptr m_xRepeatHeaderCB; + std::unique_ptr m_xRepeatHeaderNF; + std::unique_ptr m_xRepeatGroup; + std::unique_ptr m_xDontSplitCB; + std::unique_ptr m_xInsertBtn; + std::unique_ptr m_xLbFormat; + std::unique_ptr m_xWndPreview; + std::unique_ptr 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::SpinButton&, void); + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(CheckBoxHdl, weld::ToggleButton&, void); + DECL_LINK(RepeatHeaderCheckBoxHdl, weld::ToggleButton&, 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& 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 000000000..2a801ee1f --- /dev/null +++ b/sw/source/uibase/inc/javaedit.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_JAVAEDIT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_JAVAEDIT_HXX + +#include + +class SwWrtShell; +class SwFieldMgr; +class SwScriptField; + +namespace sfx2 { class FileDialogHelper; } + +class SwJavaEditDialog : public weld::GenericDialogController +{ +private: + OUString m_aText; + OUString m_aType; + + bool m_bNew; + bool m_bIsUrl; + + SwScriptField* m_pField; + std::unique_ptr m_pMgr; + SwWrtShell* m_pSh; + std::unique_ptr m_pFileDlg; + + std::unique_ptr m_xTypeED; + std::unique_ptr m_xUrlRB; + std::unique_ptr m_xEditRB; + std::unique_ptr m_xUrlPB; + std::unique_ptr m_xUrlED; + std::unique_ptr m_xEditED; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xPrevBtn; + std::unique_ptr m_xNextBtn; + + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(PrevHdl, weld::Button&, void); + DECL_LINK(NextHdl, weld::Button&, void); + DECL_LINK(RadioButtonHdl, weld::Button&, void); + DECL_LINK(InsertFileHdl, weld::Button&, void); + DECL_LINK(DlgClosedHdl, sfx2::FileDialogHelper *, void); + + 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; +}; + +#endif + +/* 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 000000000..86d08a257 --- /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 +#include +#include "labelcfg.hxx" +#include + +class SwLabItem; +class SwLabPrtPage; +class SwDBManager; +class Printer; + +class SwLabDlg : public SfxTabDialogController +{ + SwLabelConfig aLabelsCfg; + SwDBManager* pDBManager; + SwLabPrtPage* m_pPrtPage; + + std::vector aTypeIds; + std::vector aMakes; + + std::unique_ptr m_pRecs; + OUString aLstGroup; + OUString m_sBusinessCardDlg; + bool m_bLabel; + void ReplaceGroup_( const OUString &rMake ); + + virtual void PageCreated(const OString& rId, SfxTabPage &rPage) override; +public: + + SwLabDlg(weld::Window* pParent, const SfxItemSet& rSet, + SwDBManager* pDBManager, bool bLabel); + virtual ~SwLabDlg() override; + + SwLabRec* GetRecord(const OUString &rRecName, bool bCont); + void GetLabItem(SwLabItem &rItem); + + SwLabRecs &Recs() { return *m_pRecs; } + const SwLabRecs &Recs() const { return *m_pRecs; } + + std::vector &TypeIds() { return aTypeIds; } + const std::vector &TypeIds() const { return aTypeIds; } + + std::vector &Makes() { return aMakes; } + const std::vector &Makes() const { return aMakes; } + + Printer *GetPrt(); + void ReplaceGroup( const OUString &rMake ) + { + if ( rMake != 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 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 000000000..c206f67de --- /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 +#include +#include "labrec.hxx" + +#include +#include + +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 : public utl::ConfigItem +{ +private: + std::vector m_aManufacturers; + std::map< OUString, std::map > 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& 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 000000000..ec01bf38f --- /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 +#include +#include + +class SwLabCfgItem; + +class SW_DLLPUBLIC SwLabItem : 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 : public utl::ConfigItem +{ +private: + SwLabItem aItem; + bool bIsLabel; + + css::uno::Sequence GetPropertyNames() const; + + virtual void ImplCommit() override; + +public: + SwLabCfgItem(bool bLabel); + + SwLabItem& GetItem() {return 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 000000000..e8db8aab1 --- /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 + +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 000000000..1810ff476 --- /dev/null +++ b/sw/source/uibase/inc/labrec.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_LABREC_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_LABREC_HXX + +#include + +#include +#include + + +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; + long m_nHDist; + long m_nVDist; + long m_nWidth; + long m_nHeight; + long m_nLeft; + long m_nUpper; + long m_nPWidth; + long m_nPHeight; + sal_Int32 m_nCols; + sal_Int32 m_nRows; + bool m_bCont; +}; + +typedef std::vector> 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 000000000..8c93d29d3 --- /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 +#include +#include + +class SwWrtShell; +class SwView; +class EditEngine; +class EditView; +class OutlinerView; +class SfxItemSet; +class SfxRequest; +struct ESelection; +enum class SvtScriptType; + +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, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet ); + extern void SetLanguage( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, const OUString &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, sal_uInt16 nLangWhichId ); + extern LanguageType GetLanguage( SwWrtShell &rSh, sal_uInt16 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 000000000..21f4d7886 --- /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 +#include "numberingtypelistbox.hxx" + +class SwView; +class SwWrtShell; + +class SwLineNumberingDlg : public SfxDialogController +{ +private: + SwWrtShell* m_pSh; + std::unique_ptr m_xBodyContent; + std::unique_ptr m_xDivIntervalFT; + std::unique_ptr m_xDivIntervalNF; + std::unique_ptr m_xDivRowsFT; + std::unique_ptr m_xNumIntervalNF; + std::unique_ptr m_xCharStyleLB; + std::unique_ptr m_xFormatLB; + std::unique_ptr m_xPosLB; + std::unique_ptr m_xOffsetMF; + std::unique_ptr m_xDivisorED; + std::unique_ptr m_xCountEmptyLinesCB; + std::unique_ptr m_xCountFrameLinesCB; + std::unique_ptr m_xRestartEachPageCB; + std::unique_ptr m_xNumberingOnCB; + std::unique_ptr m_xNumberingOnFooterHeader; + std::unique_ptr m_xOKButton; + std::unique_ptr m_xNumIntervalFT; + std::unique_ptr m_xNumRowsFT; + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(LineOnOffHdl, weld::Button&, 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 000000000..0caecf642 --- /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 000000000..6c1ce2c4d --- /dev/null +++ b/sw/source/uibase/inc/macassgn.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_MACASSGN_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_MACASSGN_HXX + +#include +#include + +class SwWrtShell; +class SvxMacroItem; + +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::unique_ptr& 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 000000000..be6dfe137 --- /dev/null +++ b/sw/source/uibase/inc/mailconfigpage.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_MAILCONFIGPAGE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILCONFIGPAGE_HXX + +#include +#include + +class SwTestAccountSettingsDialog; +class SwMailMergeConfigItem; + +class SwMailConfigPage : public SfxTabPage +{ + friend class SwTestAccountSettingsDialog; + + std::unique_ptr m_pConfigItem; + + std::unique_ptr m_xDisplayNameED; + std::unique_ptr m_xAddressED; + std::unique_ptr m_xReplyToCB; + std::unique_ptr m_xReplyToFT; + std::unique_ptr m_xReplyToED; + std::unique_ptr m_xServerED; + std::unique_ptr m_xPortNF; + std::unique_ptr m_xSecureCB; + std::unique_ptr m_xServerAuthenticationPB; + std::unique_ptr m_xTestPB; + + DECL_LINK(ReplyToHdl, weld::ToggleButton&, void); + DECL_LINK(AuthenticationHdl, weld::Button&, void); + DECL_LINK(TestHdl, weld::Button&, void); + DECL_LINK(SecureHdl, weld::ToggleButton&, void); + +public: + SwMailConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwMailConfigPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +class SwMailConfigDlg : public SfxSingleTabDialogController +{ +public: + SwMailConfigDlg(weld::Window* pParent, 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 000000000..c4cdf253c --- /dev/null +++ b/sw/source/uibase/inc/maildispatcher.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include + +#include +#include + +#include + +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 + : 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> const & 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 + 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 const & listener); + +protected: + virtual void SAL_CALL run() override; + virtual void SAL_CALL onTerminated() override; + +private: + std::vector< ::rtl::Reference > cloneListener(); + void sendMailMessageNotifyListener(css::uno::Reference< css::mail::XMailMessage> const & message); + +private: + css::uno::Reference< css::mail::XSmtpService> m_xMailserver; + std::list< css::uno::Reference< css::mail::XMailMessage > > m_aXMessageList; + std::vector< ::rtl::Reference > m_aListenerVector; + ::osl::Mutex m_aMessageContainerMutex; + ::osl::Mutex m_aListenerContainerMutex; + ::osl::Mutex m_aThreadStatusMutex; + ::osl::Condition m_aRunCondition; + ::osl::Condition m_aWakeupCondition; + ::rtl::Reference 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 000000000..3b476a524 --- /dev/null +++ b/sw/source/uibase/inc/mailmergehelper.hxx @@ -0,0 +1,284 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(const OUString& rMailAddress); + SW_DLLPUBLIC css::uno::Reference ConnectToSmtpServer( + SwMailMergeConfigItem const & rConfigItem, + css::uno::Reference& 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 : public weld::CustomWidgetController +{ + std::unique_ptr pImpl; + std::unique_ptr m_xVScrollBar; + Link m_aSelectHdl; + + void DrawText_Impl(vcl::RenderContext& rRenderContext, const OUString& 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_LINK(ScrollHdl, weld::ScrolledWindow&,void); + +public: + SwAddressPreview(std::unique_ptr 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* pAssignments = nullptr); + + void SetSelectHdl (const Link& 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 sAddress; +public: + SwAddressIterator(const OUString& rAddress) : + sAddress(rAddress) + {} + + SwMergeAddressItem Next(); + bool HasMore() const { return !sAddress.isEmpty(); } +}; + +class SW_DLLPUBLIC SwAuthenticator : + public cppu::WeakImplHelper +{ + OUString m_aUserName; + OUString m_aPassword; + weld::Window* m_pParentWindow; +public: + SwAuthenticator() + : m_pParentWindow(nullptr) + {} + SwAuthenticator(const OUString& username, const OUString& password, weld::Window* pParent) + : m_aUserName(username) + , m_aPassword(password) + , m_pParentWindow(pParent) + {} + virtual ~SwAuthenticator() override; + + virtual OUString SAL_CALL getUserName() override; + virtual OUString SAL_CALL getPassword() override; + +}; + +class SW_DLLPUBLIC SwConnectionContext : public cppu::WeakImplHelper +{ + OUString m_sMailServer; + sal_Int16 m_nPort; + OUString m_sConnectionType; + +public: + SwConnectionContext(const OUString& rMailServer, sal_Int16 nPort, const OUString& rConnectionType); + virtual ~SwConnectionContext() override; + + virtual css::uno::Any SAL_CALL getValueByName(const OUString& Name) override; +}; + +class SwMutexBase +{ +public: + osl::Mutex m_aMutex; +}; + +class SW_DLLPUBLIC SwConnectionListener : + public SwMutexBase, + public cppu::WeakComponentImplHelper +{ + using cppu::WeakComponentImplHelperBase::disposing; + +public: + SwConnectionListener() : + cppu::WeakComponentImplHelper(m_aMutex) + {} + 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 : + public SwMutexBase, + public cppu::WeakComponentImplHelper +{ + OUString m_aMimeType; + OUString m_sBody; + OUString m_aURL; + OUString m_aName; + bool m_bIsBody; + + public: + SwMailTransferable(const OUString& rURL, const OUString& rName, const OUString& rMimeType); + SwMailTransferable(const OUString& rBody, const OUString& rMimeType); + virtual ~SwMailTransferable() override; + virtual css::uno::Any SAL_CALL getTransferData(const css::datatransfer::DataFlavor& aFlavor) override; + + virtual css::uno::Sequence SAL_CALL getTransferDataFlavors() override; + virtual sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& aFlavor) override; + + //XPropertySet + virtual css::uno::Reference 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& xListener) override; + virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, + const css::uno::Reference& aListener) override; + virtual void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, + const css::uno::Reference& aListener) override; + virtual void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, + const css::uno::Reference& aListener) override; + +}; + +class SW_DLLPUBLIC SwMailMessage : + public SwMutexBase, + public cppu::WeakComponentImplHelper +{ + OUString m_sSenderName; + OUString m_sSenderAddress; + OUString m_sReplyToAddress; + OUString m_sSubject; + + css::uno::Reference m_xBody; +// css::mail::MailMessageBody m_aBody; + + css::uno::Sequence m_aRecipients; + css::uno::Sequence m_aCcRecipients; + css::uno::Sequence m_aBccRecipients; +// css::uno::Sequence m_aAttachments; + css::uno::Sequence 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 SAL_CALL getBody() override; + virtual void SAL_CALL setBody(const css::uno::Reference& _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 SAL_CALL getRecipients() override; + virtual css::uno::Sequence SAL_CALL getCcRecipients() override; + virtual css::uno::Sequence SAL_CALL getBccRecipients() override; + virtual void SAL_CALL addAttachment(const css::mail::MailAttachment& aMailAttachment) override; + virtual css::uno::Sequence 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 000000000..0ab3c8dce --- /dev/null +++ b/sw/source/uibase/inc/mailmergewizard.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_MAILMERGEWIZARD_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_MAILMERGEWIZARD_HXX + +#include +#include + +class SwView; +class SwMailMergeConfigItem; + +using vcl::WizardTypes::WizardState; +using vcl::WizardTypes::CommitPageReason; + +#define MM_DOCUMENTSELECTPAGE 0 +#define MM_OUTPUTTYPETPAGE 1 +#define MM_ADDRESSBLOCKPAGE 2 +#define MM_GREETINGSPAGE 3 +#define MM_LAYOUTPAGE 4 + +class SwMailMergeWizard : public ::vcl::RoadmapWizardMachine +{ + SwView* m_pSwView; + OUString sDocumentURL; + bool m_bDocumentLoad; + + std::shared_ptr 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; + +protected: + virtual std::unique_ptr createPage( WizardState _nState ) override; + virtual void enterState( WizardState _nState ) override; + + virtual OUString getStateDisplayName( WizardState _nState ) const override; + +public: + SwMailMergeWizard(SwView& rView, std::shared_ptr const & rConfigItem); + virtual ~SwMailMergeWizard() override; + + SwView* GetSwView() {return m_pSwView;} + SwMailMergeConfigItem& GetConfigItem() { return *m_xConfigItem;} + + void SetReloadDocument(const OUString& rURL) {sDocumentURL = rURL;} + const OUString& GetReloadDocument() const {return 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 000000000..f409c664f --- /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 +#include + +#include +#include + +#include + +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 : public SfxDialogController +{ + friend class SwXSelChgLstnr_Impl; + + std::unique_ptr pImpl; + + SwWrtShell& rSh; + SwModuleOptions* pModOpt; + + DBManagerOptions 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 m_xBeamerWin; + + std::unique_ptr m_xAllRB; + std::unique_ptr m_xMarkedRB; + std::unique_ptr m_xFromRB; + std::unique_ptr m_xFromNF; + std::unique_ptr m_xToNF; + + std::unique_ptr m_xPrinterRB; + std::unique_ptr m_xMailingRB; + std::unique_ptr m_xFileRB; + + std::unique_ptr m_xSingleJobsCB; + std::unique_ptr m_xPasswordCB; + + std::unique_ptr m_xSaveMergedDocumentFT; + std::unique_ptr m_xSaveSingleDocRB; + std::unique_ptr m_xSaveIndividualRB; + + std::unique_ptr m_xGenerateFromDataBaseCB; + + std::unique_ptr m_xColumnFT; + std::unique_ptr m_xColumnLB; + std::unique_ptr m_xPasswordFT; + std::unique_ptr m_xPasswordLB; + std::unique_ptr m_xPathFT; + std::unique_ptr m_xPathED; + std::unique_ptr m_xPathPB; + std::unique_ptr m_xFilterFT; + std::unique_ptr m_xFilterLB; + + std::unique_ptr m_xAddressFieldLB; + std::unique_ptr m_xSubjectFT; + std::unique_ptr m_xSubjectED; + std::unique_ptr m_xFormatFT; + std::unique_ptr m_xAttachFT; + std::unique_ptr m_xAttachED; + std::unique_ptr m_xAttachPB; + std::unique_ptr m_xFormatHtmlCB; + std::unique_ptr m_xFormatRtfCB; + std::unique_ptr m_xFormatSwCB; + + std::unique_ptr m_xOkBTN; + + DECL_LINK( ButtonHdl, weld::Button&, void ); + DECL_LINK( InsertPathHdl, weld::Button&, void ); + DECL_LINK( OutputTypeHdl, weld::ToggleButton&, void ); + DECL_LINK( FilenameHdl, weld::ToggleButton&, void ); + DECL_LINK( ModifyHdl, weld::SpinButton&, void ); + DECL_LINK( SaveTypeHdl, weld::ToggleButton&, 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 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 : public weld::GenericDialogController +{ + std::unique_ptr m_xThisDocRB; +public: + SwMailMergeCreateFromDlg(weld::Window* pParent); + virtual ~SwMailMergeCreateFromDlg() override; + bool IsThisDocument() const + { + return m_xThisDocRB->get_active(); + } +}; + +class SwMailMergeFieldConnectionsDlg : public weld::GenericDialogController +{ + std::unique_ptr 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 000000000..b67f903f0 --- /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 +#include + +#include "basesh.hxx" +#include + +class SwMediaShell: 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 000000000..11ca8c726 --- /dev/null +++ b/sw/source/uibase/inc/mergetbl.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_MERGETBL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_MERGETBL_HXX + +#include + +class SwMergeTableDlg : public weld::GenericDialogController +{ + bool& m_rMergePrev; + + std::unique_ptr 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 000000000..bae35cfdc --- /dev/null +++ b/sw/source/uibase/inc/mmconfigitem.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_MMCONFIGITEM_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_MMCONFIGITEM_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#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; + long nDBRow; +}; + +class SW_DLLPUBLIC SwMailMergeConfigItem +{ + std::unique_ptr m_pImpl; + //session information - not stored in configuration + bool m_bAddressInserted; + bool m_bGreetingInserted; + sal_Int32 m_nGreetingMoves; + std::set m_aExcludedRecords; + css::uno::Reference m_xDBChangedListener; + + OUString m_sSelectedPrinter; + + SwView* m_pSourceView; + SwView* m_pTargetView; +public: + SwMailMergeConfigItem(); + ~SwMailMergeConfigItem(); + + enum Gender + { + FEMALE, + MALE, + NEUTRAL + }; + + void Commit(); + + const std::vector>& 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 IsRecordExcluded(sal_Int32 nRecord) const; + void ExcludeRecord(sal_Int32 nRecord, bool bExclude); + css::uno::Sequence< css::uno::Any> GetSelection() const; + + const css::uno::Sequence& 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 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 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 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; } + + // 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 000000000..6edca05ce --- /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 + +class SwTOXMgr; + +// insert mark for index entry +class SwMultiTOXMarkDlg : public weld::GenericDialogController +{ + DECL_LINK(SelectHdl, weld::TreeView&, void); + SwTOXMgr& m_rMgr; + sal_uInt16 m_nPos; + + std::unique_ptr m_xTextFT; + std::unique_ptr 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 000000000..a9b562493 --- /dev/null +++ b/sw/source/uibase/inc/navicfg.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +enum class RegionMode; +enum class ContentTypeId; + +class SwNavigationConfig : public utl::ConfigItem +{ + ContentTypeId nRootType; //RootType + sal_Int32 nSelectedPos; //SelectedPosition + sal_Int32 nOutlineLevel; //OutlineLevel + RegionMode nRegionMode; //InsertMode + sal_Int32 nActiveBlock; //ActiveBlock//Expand/CollapsState + bool bIsSmall; //ShowListBox + bool bIsGlobalActive; //GlobalDocMode// global view for GlobalDoc valid? + + static css::uno::Sequence GetPropertyNames(); + + virtual void ImplCommit() override; + +public: + SwNavigationConfig(); + virtual ~SwNavigationConfig() override; + + virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override; + + ContentTypeId GetRootType()const {return nRootType;} + void SetRootType(ContentTypeId nSet){ + if(nRootType != nSet) + { + SetModified(); + nRootType = nSet; + } + } + + sal_Int32 GetOutlineLevel()const {return nOutlineLevel;} + void SetOutlineLevel(sal_Int32 nSet){ + if(nOutlineLevel != nSet) + { + SetModified(); + nOutlineLevel = nSet; + } + } + + RegionMode GetRegionMode()const {return nRegionMode;} + void SetRegionMode(RegionMode nSet){ + if(nRegionMode != nSet) + { + SetModified(); + nRegionMode = nSet; + } + } + + sal_Int32 GetActiveBlock()const {return nActiveBlock;} + void SetActiveBlock(sal_Int32 nSet){ + if(nActiveBlock != nSet) + { + SetModified(); + nActiveBlock = nSet; + } + } + + bool IsSmall() const {return bIsSmall;} + void SetSmall(bool bSet){ + if(bIsSmall != bSet) + { + SetModified(); + bIsSmall = bSet; + } + } + + bool IsGlobalActive() const {return bIsGlobalActive;} + void SetGlobalActive(bool bSet){ + if(bIsGlobalActive != bSet) + { + SetModified(); + bIsGlobalActive = bSet; + } + } +}; + +#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 000000000..b6842ad91 --- /dev/null +++ b/sw/source/uibase/inc/navicont.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_NAVICONT_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVICONT_HXX + +#include + +class SwDocShell; +class TransferDataContainer; +class TransferableDataHelper; +enum class RegionMode; + +/* + navigator bookmark for distinct identification in Sw +*/ + +class NaviContentBookmark +{ + OUString aUrl; // URL including jump mark + OUString aDescr; // description + long nDocSh; // address of DocShell + RegionMode nDefDrag; // description contains defaultDragType + +public: + NaviContentBookmark(); + NaviContentBookmark( const OUString &rUrl, const OUString& rDesc, + RegionMode nDragType, const SwDocShell* ); + + const OUString& GetURL() const { return aUrl; } + const OUString& GetDescription() const { return aDescr; } + RegionMode GetDefaultDragType() const { return nDefDrag; } + void Copy( TransferDataContainer& rData ) const; + bool Paste( TransferableDataHelper& rData ); +}; + +#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 000000000..fee94525d --- /dev/null +++ b/sw/source/uibase/inc/navipi.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_NAVIPI_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_NAVIPI_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "conttree.hxx" +#include +#include + +class SwWrtShell; +class SwNavigationPI; +class SwNavigationChild; +class SfxBindings; +class SwNavigationConfig; +class SwView; +class SfxObjectShellLock; +class SfxChildWindowContext; +enum class RegionMode; +class SpinField; + +class SwNavigationPI : public PanelLayout + , public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface + , public SfxListener +{ + friend class SwNavigationChild; + friend class SwContentTree; + friend class SwGlobalTree; + friend class SwNavigationPIUIObject; + + ::sfx2::sidebar::ControllerItem m_aDocFullName; + ::sfx2::sidebar::ControllerItem m_aPageStats; + + std::unique_ptr m_xContent1ToolBox; + std::unique_ptr m_xContent2ToolBox; + std::unique_ptr m_xContent3ToolBox; + std::unique_ptr m_xContent1Dispatch; + std::unique_ptr m_xHeadingsMenu; + std::unique_ptr m_xDragModeMenu; + std::unique_ptr m_xUpdateMenu; + std::unique_ptr m_xInsertMenu; + std::unique_ptr m_xGlobalToolBox; + std::unique_ptr m_xEdit; + std::unique_ptr m_xContentBox; + std::unique_ptr m_xContentTree; + std::unique_ptr m_xGlobalBox; + std::unique_ptr m_xGlobalTree; + std::unique_ptr m_xDocListBox; + Idle m_aPageChgIdle; + OUString m_sContentFileName; + OUString m_aStatusArr[4]; + + std::unique_ptr m_pxObjectShell; + 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; + + bool IsZoomedIn() const {return m_bIsZoomedIn;} + void ZoomOut(); + void ZoomIn(); + + void FillBox(); + + DECL_LINK( DocListBoxSelectHdl, weld::ComboBox&, void ); + DECL_LINK( ToolBoxSelectHdl, const OString&, void ); + DECL_LINK( ToolBoxClickHdl, const OString&, void ); + DECL_LINK( ToolBox2DropdownClickHdl, const OString&, void ); + DECL_LINK( ToolBox3DropdownClickHdl, const OString&, void ); + DECL_LINK( DoneLink, SfxPoolItem const *, void ); + DECL_LINK( DropModeMenuSelectHdl, const OString&, void ); + DECL_LINK( HeadingsMenuSelectHdl, const OString&, void ); + DECL_LINK( GlobalMenuSelectHdl, const OString&, void ); + DECL_LINK( ChangePageHdl, Timer*, void ); + DECL_LINK( PageEditModifyHdl, weld::SpinButton&, void ); + DECL_LINK( EditActionHdl, weld::Entry&, bool ); + bool EditAction(); + void UsePage(); + +protected: + + // 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;} + +public: + + static VclPtr Create(vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings); + SwNavigationPI(vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* _pBindings); + virtual ~SwNavigationPI() override; + virtual void dispose() 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 {}; + + virtual void StateChanged(StateChangedType nStateChange) override; + + static OUString CreateDropFileName( 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; + + FactoryFunction GetUITestFactory() const override; +}; + +class SwNavigationChild : public SfxChildWindowContext +{ +public: + SwNavigationChild( vcl::Window* , + sal_uInt16 nId, + SfxBindings* ); + + //! soon obsolete ! + static std::unique_ptr CreateImpl(vcl::Window *pParent, + SfxBindings *pBindings, SfxChildWinInfo* pInfo ); + static void RegisterChildWindowContext(SfxModule *pMod); +}; + +#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 000000000..858b990fd --- /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 + +#include + +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 000000000..4bc26ecb1 --- /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 +#include + +#include "basesh.hxx" +#include + +class SwNavigationShell: 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 000000000..9d5360669 --- /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 +#include "numprevw.hxx" +#include + +class SwWrtShell; +class SvxBrushItem; +class SwOutlineTabDialog; + +class SwNumPositionTabPage : public SfxTabPage +{ + std::unique_ptr pActNum; + SwNumRule* pSaveNum; + SwWrtShell* pWrtSh; + + SwOutlineTabDialog* pOutlineDlg; + sal_uInt16 nActNumLvl; + + bool bModified : 1; + bool bPreset : 1; + bool bInInintControl : 1; // work around modify-error; should be resolved from 391 on + bool bLabelAlignmentPosAndSpaceModeActive; + + NumberingPreview m_aPreviewWIN; + + std::unique_ptr m_xLevelLB; + std::unique_ptr m_xPositionFrame; + + // former set of controls shown for numbering rules containing list level + // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_WIDTH_AND_POSITION + std::unique_ptr m_xDistBorderFT; + std::unique_ptr m_xDistBorderMF; + std::unique_ptr m_xRelativeCB; + std::unique_ptr m_xIndentFT; + std::unique_ptr m_xIndentMF; + std::unique_ptr m_xDistNumFT; + std::unique_ptr m_xDistNumMF; + std::unique_ptr m_xAlignFT; + std::unique_ptr m_xAlignLB; + + // new set of controls shown for numbering rules containing list level + // attributes in SvxNumberFormat::SvxNumPositionAndSpaceMode == LABEL_ALIGNMENT + std::unique_ptr m_xLabelFollowedByFT; + std::unique_ptr m_xLabelFollowedByLB; + std::unique_ptr m_xListtabFT; + std::unique_ptr m_xListtabMF; + std::unique_ptr m_xAlign2FT; + std::unique_ptr m_xAlign2LB; + std::unique_ptr m_xAlignedAtFT; + std::unique_ptr m_xAlignedAtMF; + std::unique_ptr m_xIndentAtFT; + std::unique_ptr m_xIndentAtMF; + std::unique_ptr m_xStandardPB; + std::unique_ptr 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::ToggleButton&, 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 Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + void SetOutlineTabDialog(SwOutlineTabDialog* pDlg){pOutlineDlg = pDlg;} + void SetWrtShell(SwWrtShell* pSh); +#ifdef DBG_UTIL + void SetModified(); +#else + void SetModified() + { + bModified = true; + m_aPreviewWIN.SetLevel(nActNumLvl); + m_aPreviewWIN.Invalidate(); + } +#endif +}; + +class SwSvxNumBulletTabDialog final : public SfxTabDialogController +{ + SwWrtShell& rWrtSh; + + virtual short Ok() override; + virtual void PageCreated(const OString& rPageId, SfxTabPage& rPage) override; + DECL_LINK(RemoveNumberingHdl, weld::Button&, void); + + std::unique_ptr m_xDummyCombo; + +public: + SwSvxNumBulletTabDialog(weld::Window* pParent, + const SfxItemSet* pSwItemSet, + 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 000000000..b264dcf8c --- /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 +#include +#include +#include +#include + +enum class SwInsertNumTypes +{ + NoNumbering = 0x01, + Extended = 0x02 +}; + +namespace o3tl { + template<> struct typed_flags : is_typed_flags {}; +}; + +struct SwNumberingTypeListBox_Impl; + +class SW_DLLPUBLIC SwNumberingTypeListBox +{ + std::unique_ptr m_xWidget; + std::unique_ptr m_xImpl; + +public: + SwNumberingTypeListBox(std::unique_ptr pWidget); + ~SwNumberingTypeListBox(); + + void connect_changed(const Link& 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 000000000..f4f75e32d --- /dev/null +++ b/sw/source/uibase/inc/numfmtlb.hxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +class SwView; + +class SW_DLLPUBLIC SwNumFormatBase +{ +protected: + SvNumFormatType nCurrFormatType; + bool mbCurrFormatTypeNeedsInit; + sal_Int32 nStdEntry; + bool bOneArea; + sal_uInt32 nDefFormat; + LanguageType eCurLanguage; + bool bShowLanguageControl; //determine whether the language control has + //to be shown in the number format dialog + bool bUseAutomaticLanguage;//determine whether language is automatically assigned +public: + SwNumFormatBase(); + + void SetAutomaticLanguage(bool bSet) { bUseAutomaticLanguage = bSet; } + bool IsAutomaticLanguage()const { return bUseAutomaticLanguage; } + SvNumFormatType GetFormatType() const { return nCurrFormatType; } + LanguageType GetCurLanguage() const { return eCurLanguage;} + void SetLanguage(LanguageType eSet) { eCurLanguage = eSet; } + void SetShowLanguageControl(bool bSet) { bShowLanguageControl = bSet; } + SAL_DLLPRIVATE static double GetDefValue(const SvNumFormatType nFormatType); + void SetOneArea(bool bOnlyOne) { 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 : public SwNumFormatBase +{ + std::unique_ptr mxControl; + + DECL_DLLPRIVATE_LINK( SelectHdl, weld::ComboBox&, void ); + + virtual void Init() override; + +public: + NumFormatListBox(std::unique_ptr 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& rLink) { mxControl->connect_changed(rLink); } +}; + +class SW_DLLPUBLIC SwNumFormatTreeView : public SwNumFormatBase +{ + std::unique_ptr mxControl; + + DECL_DLLPRIVATE_LINK( SelectHdl, weld::TreeView&, void ); + + virtual void Init() override; + +public: + SwNumFormatTreeView(std::unique_ptr 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(); } + bool get_value_changed_from_saved() const { return mxControl->get_value_changed_from_saved(); } + void save_value() { return mxControl->save_value(); } + void show() { mxControl->show(); } + void hide() { mxControl->hide(); } + 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& rLink) { mxControl->connect_row_activated(rLink); } + + void set_sensitive(bool bSensitive) { mxControl->set_sensitive(bSensitive); } + void connect_changed(const Link& rLink) { mxControl->connect_changed(rLink); } +}; + +#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 000000000..1589220e6 --- /dev/null +++ b/sw/source/uibase/inc/numpara.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_NUMPARA_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_NUMPARA_HXX + +#include +#include + +// with this TabPage numbering settings at the paragraph / paragraph style +// are performed. +class SwParagraphNumTabPage final : public SfxTabPage +{ + // #outlinelevel# + const OUString msOutlineNumbering; + + bool bModified : 1; + bool bCurNumrule : 1; + + std::unique_ptr m_xOutlineStartBX; + std::unique_ptr m_xOutlineLvLB; + std::unique_ptr m_xNumberStyleBX; + std::unique_ptr m_xNumberStyleLB; + std::unique_ptr m_xEditNumStyleBtn; + + std::unique_ptr m_xNewStartCB; + std::unique_ptr m_xNewStartBX; + std::unique_ptr m_xNewStartNumberCB; + std::unique_ptr m_xNewStartNF; + + std::unique_ptr m_xCountParaFram; + std::unique_ptr m_xCountParaCB; + std::unique_ptr m_xRestartParaCountCB; + + std::unique_ptr m_xRestartBX; + std::unique_ptr m_xRestartNF; + + DECL_LINK(NewStartHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(StyleHdl_Impl, weld::ComboBox&,void); + DECL_LINK(LineCountHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(EditNumStyleHdl_Impl, weld::Button&, void); + DECL_LINK(EditNumStyleSelectHdl_Impl, weld::ComboBox&, void); + + static const sal_uInt16 aPageRg[]; + + static bool 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 Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rSet ); + static const sal_uInt16* GetRanges() { return 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 000000000..a5510a6d4 --- /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 + +class SwNumRule; +namespace rtl { class OUString; } + +class NumberingPreview : public weld::CustomWidgetController +{ + const SwNumRule* pActNum; + vcl::Font aStdFont; + long nPageWidth; + const OUString* pOutlineNames; + bool bPosition; + sal_uInt16 nActLevel; + +private: + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + +public: + NumberingPreview() + : pActNum(nullptr) + , nPageWidth(0) + , pOutlineNames(nullptr) + , bPosition(false) + , nActLevel(USHRT_MAX) + { + } + + void SetNumRule(const SwNumRule* pNum) + { + pActNum = pNum; + Invalidate(); + } + + void SetPageWidth(long nPgWidth) + {nPageWidth = nPgWidth;} + void SetOutlineNames(const OUString* pNames) + {pOutlineNames = pNames;} + void SetPositionMode() + { bPosition = true;} + void SetLevel(sal_uInt16 nSet) {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 000000000..30979029e --- /dev/null +++ b/sw/source/uibase/inc/olesh.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_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(); + +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 000000000..047c21083 --- /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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_OLMENU_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_OLMENU_HXX + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +//! 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 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, + const 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; + } + + void Execute( const tools::Rectangle& rPopupPos, vcl::Window* pWin ); + void Execute( sal_uInt16 nId ); +}; + +#endif + +/* 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 000000000..e087d3852 --- /dev/null +++ b/sw/source/uibase/inc/optcomp.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_OPTCOMP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_OPTCOMP_HXX + +#include +#include +#include +#include +#include + +class SwWrtShell; +struct SwCompatibilityOptPage_Impl; + +class SwCompatibilityOptPage : public SfxTabPage +{ +private: + // config item + SvtCompatibilityOptions m_aConfigItem; + // config item + SvtCompatibilityViewOptions m_aViewConfigItem; + // text of the user entry + OUString m_sUserEntry; + // shell of the current document + SwWrtShell* m_pWrtShell; + // impl object + std::unique_ptr m_pImpl; + // saved options after "Reset"; used in "FillItemSet" for comparison + sal_uInt32 m_nSavedOptions; + bool m_bSavedMSFormsMenuOption; + + // controls + std::unique_ptr m_xMain; + std::unique_ptr m_xGlobalOptionsFrame; + std::unique_ptr m_xFormattingLB; + std::unique_ptr m_xGlobalOptionsLB; + std::unique_ptr m_xOptionsLB; + std::unique_ptr m_xGlobalOptionsCLB; + std::unique_ptr 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 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/optload.hxx b/sw/source/uibase/inc/optload.hxx new file mode 100644 index 000000000..1db4fcbf5 --- /dev/null +++ b/sw/source/uibase/inc/optload.hxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_OPTLOAD_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_OPTLOAD_HXX + +#include +#include + +#include +#include +#include +#include + +#include + +class SwFieldMgr; +class SvTreeListEntry; +class SwWrtShell; + +class SwFieldUnitTable +{ +public: + static OUString GetString(sal_uInt32 i); + static sal_uInt32 Count(); + static FieldUnit GetValue(sal_uInt32 i); +}; + +class TextFilterAutoConvert : public TextFilter +{ +private: + OUString m_sLastGoodText; + OUString m_sNone; +public: + TextFilterAutoConvert(const OUString &rNone) + : m_sNone(rNone) + { + } + virtual OUString filter(const OUString &rText) override; +}; + +class SwLoadOptPage : public SfxTabPage +{ +private: + SwWrtShell* m_pWrtShell; + sal_uInt16 m_nLastTab; + sal_Int32 m_nOldLinkMode; + + std::unique_ptr m_xAlwaysRB; + std::unique_ptr m_xRequestRB; + std::unique_ptr m_xNeverRB; + + std::unique_ptr m_xAutoUpdateFields; + std::unique_ptr m_xAutoUpdateCharts; + + std::unique_ptr m_xMetricLB; + std::unique_ptr m_xTabFT; + std::unique_ptr m_xTabMF; + std::unique_ptr m_xUseSquaredPageMode; + std::unique_ptr m_xUseCharUnit; + std::unique_ptr m_xWordCountED; + std::unique_ptr m_xShowStandardizedPageCount; + std::unique_ptr m_xStandardizedPageSizeNF; + + DECL_LINK(MetricHdl, weld::ComboBox&, void); + DECL_LINK(StandardizedPageCountCheckHdl, weld::Button&, void); + +public: + SwLoadOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwLoadOptPage() override; + + static std::unique_ptr Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +class SwCaptionOptDlg : public SfxSingleTabDialogController +{ +public: + SwCaptionOptDlg(weld::Window* pParent, const SfxItemSet& rSet); +}; + +class SwCaptionPreview : 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 : 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 pMgr; + bool bHTMLMode; + + TextFilterAutoConvert m_aTextFilter; + + SwCaptionPreview m_aPreview; + std::unique_ptr m_xCheckLB; + std::unique_ptr m_xLbCaptionOrder; + + std::unique_ptr m_xSettingsGroup; + std::unique_ptr m_xCategoryBox; + std::unique_ptr m_xFormatText; + std::unique_ptr m_xFormatBox; + //#i61007# order of captions + std::unique_ptr m_xNumberingSeparatorFT; + std::unique_ptr m_xNumberingSeparatorED; + std::unique_ptr m_xTextText; + std::unique_ptr m_xTextEdit; + std::unique_ptr m_xPosBox; + + std::unique_ptr m_xNumCapt; + std::unique_ptr m_xLbLevel; + std::unique_ptr m_xEdDelim; + + std::unique_ptr m_xCategory; + std::unique_ptr m_xCharStyleLB; + std::unique_ptr m_xApplyBorderCB; + std::unique_ptr m_xPreview; + + typedef std::pair row_col; + + 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 row_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 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/optpage.hxx b/sw/source/uibase/inc/optpage.hxx new file mode 100644 index 000000000..73062bb3b --- /dev/null +++ b/sw/source/uibase/inc/optpage.hxx @@ -0,0 +1,384 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_OPTPAGE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_OPTPAGE_HXX +#include + +#include +#include +#include +#include +#include "fontcfg.hxx" +class SfxPrinter; +class SwStdFontConfig; +class SwWrtShell; +class FontList; + +// Tools->Options->Writer->View +// Tools->Options->Writer/Web->View +class SwContentOptPage : public SfxTabPage +{ + std::unique_ptr m_xCrossCB; + + std::unique_ptr m_xHMetric; + std::unique_ptr m_xVRulerCBox; + std::unique_ptr m_xVRulerRightCBox; + std::unique_ptr m_xVMetric; + std::unique_ptr m_xSmoothCBox; + + std::unique_ptr m_xGrfCB; + std::unique_ptr m_xTableCB; + std::unique_ptr m_xDrwCB; + std::unique_ptr m_xPostItCB; + + std::unique_ptr m_xSettingsFrame; + std::unique_ptr m_xSettingsLabel; + std::unique_ptr m_xMetricLabel; + std::unique_ptr m_xMetricLB; + + std::unique_ptr m_xShowInlineTooltips; + std::unique_ptr m_xFieldHiddenCB; + std::unique_ptr m_xFieldHiddenParaCB; + + DECL_LINK(VertRulerHdl, weld::ToggleButton&, void); +public: + SwContentOptPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwContentOptPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet(SfxItemSet* rSet) override; + virtual void Reset(const SfxItemSet* rSet) override; +}; + +// TabPage printer settings additions +class SwAddPrinterTabPage : public SfxTabPage +{ + OUString sNone; + bool bAttrModified; + bool bPreview; + + std::unique_ptr m_xGrfCB; + std::unique_ptr m_xCtrlFieldCB; + std::unique_ptr m_xBackgroundCB; + std::unique_ptr m_xBlackFontCB; + std::unique_ptr m_xPrintHiddenTextCB; + std::unique_ptr m_xPrintTextPlaceholderCB; + + std::unique_ptr m_xPagesFrame; + std::unique_ptr m_xLeftPageCB; + std::unique_ptr m_xRightPageCB; + std::unique_ptr m_xProspectCB; + std::unique_ptr m_xProspectCB_RTL; + + std::unique_ptr m_xCommentsFrame; + std::unique_ptr m_xNoRB; + std::unique_ptr m_xOnlyRB; + std::unique_ptr m_xEndRB; + std::unique_ptr m_xEndPageRB; + std::unique_ptr m_xInMarginsRB; + + std::unique_ptr m_xPrintEmptyPagesCB; + std::unique_ptr m_xPaperFromSetupCB; + std::unique_ptr m_xFaxLB; + + DECL_LINK(AutoClickHdl, weld::ToggleButton&, 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 Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet(SfxItemSet* rSet) override; + virtual void Reset(const SfxItemSet* rSet) override; + void SetFax(const std::vector& ); + void SetPreview(bool bPrev); + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +class SwStdFontTabPage : public SfxTabPage +{ + OUString m_sShellStd; + OUString m_sShellTitle; + OUString m_sShellList; + OUString m_sShellLabel; + OUString m_sShellIndex; + + VclPtr m_pPrt; + std::unique_ptr 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; + + bool m_bListHeightDefault :1; + bool m_bLabelHeightDefault :1; + bool m_bIndexHeightDefault :1; + + sal_uInt8 m_nFontGroup; //fontcfg.hxx: FONT_GROUP_[STANDARD|CJK|CTL] + + OUString m_sScriptWestern; + OUString m_sScriptAsian; + OUString m_sScriptComplex; + + std::unique_ptr m_xLabelFT; + std::unique_ptr m_xStandardBox; + std::unique_ptr m_xStandardHeightLB; + std::unique_ptr m_xTitleBox; + std::unique_ptr m_xTitleHeightLB; + std::unique_ptr m_xListBox; + std::unique_ptr m_xListHeightLB; + std::unique_ptr m_xLabelBox; + std::unique_ptr m_xLabelHeightLB; + std::unique_ptr m_xIdxBox; + std::unique_ptr m_xIndexHeightLB; + std::unique_ptr 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 Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + virtual ~SwStdFontTabPage() override; + + virtual bool FillItemSet(SfxItemSet* rSet) override; + virtual void Reset(const SfxItemSet* rSet) override; + + virtual void PageCreated(const SfxAllItemSet& aSet) override; +}; + +class SwTableOptionsTabPage : public SfxTabPage +{ + SwWrtShell* m_pWrtShell; + bool m_bHTMLMode; + + std::unique_ptr m_xHeaderCB; + std::unique_ptr m_xRepeatHeaderCB; + std::unique_ptr m_xDontSplitCB; + std::unique_ptr m_xBorderCB; + + std::unique_ptr m_xNumFormattingCB; + std::unique_ptr m_xNumFormatFormattingCB; + std::unique_ptr m_xNumAlignmentCB; + + std::unique_ptr m_xRowMoveMF; + std::unique_ptr m_xColMoveMF; + + std::unique_ptr m_xRowInsertMF; + std::unique_ptr m_xColInsertMF; + + std::unique_ptr m_xFixRB; + std::unique_ptr m_xFixPropRB; + std::unique_ptr m_xVarRB; + + DECL_LINK(CheckBoxHdl, weld::Button&, void); + +public: + SwTableOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwTableOptionsTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + 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 : public SfxTabPage +{ + SwWrtShell * m_pWrtShell; + + //nonprinting characters + std::unique_ptr m_xParaCB; + std::unique_ptr m_xSHyphCB; + std::unique_ptr m_xSpacesCB; + std::unique_ptr m_xHSpacesCB; + std::unique_ptr m_xTabCB; + std::unique_ptr m_xTabLabel; + std::unique_ptr m_xBreakCB; + std::unique_ptr m_xCharHiddenCB; + std::unique_ptr m_xBookmarkCB; + std::unique_ptr m_xBookmarkLabel; + + std::unique_ptr m_xDirectCursorFrame; + std::unique_ptr m_xOnOffCB; + + std::unique_ptr m_xDirectCursorFillMode; + std::unique_ptr m_xCursorProtFrame; + std::unique_ptr m_xCursorInProtCB; + + std::unique_ptr m_xMathBaselineAlignmentCB; + +public: + SwShdwCursorOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwShdwCursorOptionsTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + + virtual void PageCreated( const SfxAllItemSet& aSet ) override; +}; + +// mark preview +class SwMarkPreview : 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 aPage; + tools::Rectangle aLeftPagePrtArea; + tools::Rectangle aRightPagePrtArea; + + sal_uInt16 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) { nMarkPos = nPos; } +}; + +// redlining options +class SwRedlineOptionsTabPage : public SfxTabPage +{ + std::unique_ptr m_xInsertLB; + std::unique_ptr m_xInsertColorLB; + std::unique_ptr m_xInsertedPreviewWN; + std::unique_ptr m_xInsertedPreview; + + std::unique_ptr m_xDeletedLB; + std::unique_ptr m_xDeletedColorLB; + std::unique_ptr m_xDeletedPreviewWN; + std::unique_ptr m_xDeletedPreview; + + std::unique_ptr m_xChangedLB; + std::unique_ptr m_xChangedColorLB; + std::unique_ptr m_xChangedPreviewWN; + std::unique_ptr m_xChangedPreview; + + std::unique_ptr m_xMarkPosLB; + std::unique_ptr m_xMarkColorLB; + std::unique_ptr m_xMarkPreviewWN; + std::unique_ptr 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 Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; +}; + +// TabPage test settings for SW + +#ifdef DBG_UTIL + +class SwTestTabPage : public SfxTabPage +{ +public: + SwTestTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwTestTabPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + virtual bool FillItemSet( SfxItemSet* rSet ) override; + virtual void Reset( const SfxItemSet* rSet ) override; + +private: + bool bAttrModified; + + std::unique_ptr m_xTest1CBox; + std::unique_ptr m_xTest2CBox; + std::unique_ptr m_xTest3CBox; + std::unique_ptr m_xTest4CBox; + std::unique_ptr m_xTest5CBox; + std::unique_ptr m_xTest6CBox; + std::unique_ptr m_xTest7CBox; + std::unique_ptr m_xTest8CBox; + std::unique_ptr m_xTest9CBox; + std::unique_ptr m_xTest10CBox; + + void Init(); + DECL_LINK(AutoClickHdl, weld::Button&, void); +}; +#endif // DBG_UTIL + +class SwCompareOptionsTabPage : public SfxTabPage +{ + std::unique_ptr m_xAutoRB; + std::unique_ptr m_xWordRB; + std::unique_ptr m_xCharRB; + std::unique_ptr m_xRsidCB; + std::unique_ptr m_xIgnoreCB; + std::unique_ptr m_xLenNF; + std::unique_ptr m_xStoreRsidCB; + + DECL_LINK(ComparisonHdl, weld::Button&, void); + DECL_LINK(IgnoreHdl, weld::Button&, void); + +public: + SwCompareOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + virtual ~SwCompareOptionsTabPage() override; + + static std::unique_ptr 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/outline.hxx b/sw/source/uibase/inc/outline.hxx new file mode 100644 index 000000000..f9c3c1f15 --- /dev/null +++ b/sw/source/uibase/inc/outline.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_OUTLINE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_OUTLINE_HXX + +#include +#include +#include +#include "numprevw.hxx" +#include "numberingtypelistbox.hxx" +#include + +class SwWrtShell; +class SwNumRule; +class SwChapterNumRules; + +class SwOutlineTabDialog final : public SfxTabDialogController +{ + static sal_uInt16 nNumLevel; + + OUString aCollNames[MAXLEVEL]; + + SwWrtShell& rWrtSh; + std::unique_ptr xNumRule; + SwChapterNumRules* pChapterNumRules; + + bool bModified : 1; + + std::unique_ptr m_xMenuButton; + + DECL_LINK(CancelHdl, weld::Button&, void); + DECL_LINK(FormHdl, weld::ToggleButton&, void); + DECL_LINK(MenuSelectHdl, const OString&, void); + + virtual void PageCreated(const OString& rPageId, SfxTabPage& rPage) override; + virtual short Ok() override; + +public: + SwOutlineTabDialog(weld::Window* pParent, const SfxItemSet* pSwItemSet, SwWrtShell &); + virtual ~SwOutlineTabDialog() override; + + SwNumRule* GetNumRule() { return xNumRule.get(); } + sal_uInt16 GetLevel(const OUString &rFormatName) const; + OUString* GetCollNames() {return aCollNames;} + + static sal_uInt16 GetActNumLevel() {return nNumLevel;} + static void SetActNumLevel(sal_uInt16 nSet) {nNumLevel = nSet;} +}; + +class SwOutlineSettingsTabPage : public SfxTabPage +{ + OUString aNoFormatName; + OUString aSaveCollNames[MAXLEVEL]; + SwWrtShell* pSh; + SwNumRule* pNumRule; + OUString* pCollNames; + sal_uInt16 nActLevel; + NumberingPreview m_aPreviewWIN; + + std::unique_ptr m_xLevelLB; + std::unique_ptr m_xCollBox; + std::unique_ptr m_xNumberBox; + std::unique_ptr m_xCharFormatLB; + std::unique_ptr m_xAllLevelFT; + std::unique_ptr m_xAllLevelNF; + std::unique_ptr m_xPrefixED; + std::unique_ptr m_xSuffixED; + std::unique_ptr m_xStartEdit; + std::unique_ptr 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 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) + { + pNumRule = pRule; + m_aPreviewWIN.SetNumRule(pNumRule); + } +}; + +#endif + +/* 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 000000000..c417c7223 --- /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 000000000..4be18c634 --- /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 + +class SwBackgroundDlg : 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 000000000..c174aee48 --- /dev/null +++ b/sw/source/uibase/inc/pgfnote.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_PGFNOTE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_PGFNOTE_HXX + +#include + +#include +#include + +// footnote settings TabPage +class SwFootNotePage: public SfxTabPage +{ + static const sal_uInt16 aPageRg[]; +public: + SwFootNotePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + virtual ~SwFootNotePage() override; + + static const sal_uInt16* GetRanges() { return aPageRg; } + + virtual bool FillItemSet(SfxItemSet *rSet) override; + virtual void Reset(const SfxItemSet *rSet) override; + +private: + + long lMaxHeight; + + std::unique_ptr m_xMaxHeightPageBtn; + std::unique_ptr m_xMaxHeightBtn; + std::unique_ptr m_xMaxHeightEdit; + std::unique_ptr m_xDistEdit; + std::unique_ptr m_xLinePosBox; + std::unique_ptr m_xLineTypeBox; + std::unique_ptr m_xLineWidthEdit; + std::unique_ptr m_xLineColorBox; + std::unique_ptr m_xLineLengthEdit; + std::unique_ptr m_xLineDistEdit; + + DECL_LINK(HeightPage, weld::ToggleButton&, void); + DECL_LINK(HeightMetric, weld::ToggleButton&, 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; + +}; + +#endif + +/* 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 000000000..a43aee7b4 --- /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 +#include "colex.hxx" +#include +#include +#include + +// TabPage Format/(Styles/)Page/Text grid +class SwTextGridPage: 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 m_xNoGridRB; + std::unique_ptr m_xLinesGridRB; + std::unique_ptr m_xCharsGridRB; + std::unique_ptr m_xSnapToCharsCB; + std::unique_ptr m_xExampleWN; + std::unique_ptr m_xLayoutFL; + std::unique_ptr m_xLinesPerPageNF; + std::unique_ptr m_xLinesRangeFT; + std::unique_ptr m_xTextSizeMF; + std::unique_ptr m_xCharsPerLineFT; + std::unique_ptr m_xCharsPerLineNF; + std::unique_ptr m_xCharsRangeFT; + std::unique_ptr m_xCharWidthFT; + std::unique_ptr m_xCharWidthMF; + std::unique_ptr m_xRubySizeFT; + std::unique_ptr m_xRubySizeMF; + std::unique_ptr m_xRubyBelowCB; + std::unique_ptr m_xDisplayFL; + std::unique_ptr m_xDisplayCB; + std::unique_ptr m_xPrintCB; + std::unique_ptr 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::ToggleButton&, void); + DECL_LINK(CharorLineChangedHdl, weld::SpinButton&, void); + DECL_LINK(TextSizeChangedHdl, weld::MetricSpinButton&, void); + DECL_LINK(ColorModifyHdl, ColorListBox&, void); + DECL_LINK(GridModifyClickHdl, weld::ToggleButton&, void); + DECL_LINK(DisplayGridHdl, weld::ToggleButton&, void); + +public: + SwTextGridPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwTextGridPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* 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 000000000..f9e682c51 --- /dev/null +++ b/sw/source/uibase/inc/prcntfld.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_PRCNTFLD_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_PRCNTFLD_HXX + +#include +#include +#include + +class SW_DLLPUBLIC SwPercentField +{ + std::unique_ptr m_pField; + + int nRefValue; // 100% value for conversion (in Twips) + int nOldMax; + int nOldMin; + int nOldSpinSize; + int nOldPageSize; + int nLastPercent; + int nLastValue; + sal_uInt16 nOldDigits; + FieldUnit eOldUnit; + bool 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 pControl); + const weld::MetricSpinButton* get() const { return m_pField.get(); } + weld::MetricSpinButton* get() { return m_pField.get(); } + void connect_value_changed(const Link& 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(int nNewMin) { m_pField->set_min(nNewMin, FieldUnit::NONE); } + void SetMetricFieldMax(int nNewMax) { m_pField->set_max(nNewMax, FieldUnit::NONE); } + + void set_value(int nNewValue, FieldUnit eInUnit = FieldUnit::NONE); + int get_value(FieldUnit eOutUnit = FieldUnit::NONE); + + void set_min(int nNewMin, FieldUnit eInUnit); + void set_max(int nNewMax, FieldUnit eInUnit); + + int get_min(FieldUnit eOutUnit = FieldUnit::NONE) const { return m_pField->get_min(eOutUnit); } + + int NormalizePercent(int nValue); + int DenormalizePercent(int nValue); + + void SetRefValue(int nValue); + int GetRealValue(FieldUnit eOutUnit); + + int Convert(int nValue, FieldUnit eInUnit, FieldUnit eOutUnit); + + void ShowPercent(bool bPercent); + + void LockAutoCalculation(bool bLock) {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 000000000..38f743f9c --- /dev/null +++ b/sw/source/uibase/inc/pview.hxx @@ -0,0 +1,302 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include + +class SwViewOption; +class SwDocShell; +class SwScrollbar; +class SwViewShell; +class SwPagePreview; +class ImageButton; +class Button; +class SwRect; +class DataChangedEvent; +class CommandEvent; +class SvtAccessibilityOptions; +class SwPagePreviewLayout; + +// Delete member and its accessor +class SAL_DLLPUBLIC_RTTI SwPagePreviewWin : public vcl::Window +{ + SwViewShell* mpViewShell; + sal_uInt16 mnSttPage; + sal_uInt8 mnRow; + sal_uInt8 mnCol; + Size maPxWinSize; + Fraction maScale; + SwPagePreview& mrView; + bool mbCalcScaleForPreviewLayout; + tools::Rectangle maPaintedPreviewDocRect; + SwPagePreviewLayout* mpPgPreviewLayout; + + void SetPagePreview( sal_uInt8 nRow, sal_uInt8 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_uInt8 GetRow() const + { + return mnRow; + } + + sal_uInt8 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_uInt8 nNewRow, sal_uInt8 nNewCol ); + + void SetWinSize( const Size& rNewSize ); + + // Add , + 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(long nXMove, 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 or of + + @return boolean indicating, if book preview mode has changed. + */ + bool SetBookPreviewMode( const bool _bBookPreview ); + + virtual css::uno::Reference CreateAccessible() override; +}; + +/** + * View of a document + */ +class SW_DLLPUBLIC SwPagePreview: public SfxViewShell +{ + // ViewWindow and handle to core + // current dispatcher shell + VclPtr 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 m_pHScrollbar; + VclPtr m_pVScrollbar; + bool mbHScrollbarEnabled : 1; + bool mbVScrollbarEnabled : 1; + // dummy window for filling the lower right edge when both scrollbars are active + VclPtr m_pScrollFill; + + 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(ScrollHdl, ScrollBar*, void); + DECL_DLLPRIVATE_LINK(EndScrollHdl, ScrollBar*, void); + 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 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 instance, if existing. + */ + SAL_DLLPRIVATE void ExecPgUpAndPgDown( const bool _bPgUp, + SfxRequest* _pReq ); + +protected: + virtual void InnerResizePixel( const Point &rOfs, const Size &rSize, bool inplaceEditModeChange ) override; + virtual void OuterResizePixel( const Point &rOfs, const Size &rSize ) 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(SvtAccessibilityOptions const & rAccessibilityOptions); + + // Inline method to request values of new members + // and + 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* pFrame, 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 000000000..910f23ce2 --- /dev/null +++ b/sw/source/uibase/inc/redlndlg.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_REDLNDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_REDLNDLG_HXX +#include +#include "chldwrap.hxx" +#include +#include +#include +#include +#include +#include + +#include +#include + +class SwChildWinWrapper; + +struct SwRedlineDataChild +{ + const SwRedlineData* pChild; // link to original stacked data + const SwRedlineDataChild* pNext; // link to stacked data + std::unique_ptr xTLBChild; // corresponding TreeListBox entry +}; + +struct SwRedlineDataParent +{ + const SwRedlineData* pData; // RedlineDataPtr + const SwRedlineDataChild* pNext; // link to stacked data + std::unique_ptr 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 > {}; + +class SW_DLLPUBLIC SwRedlineAcceptDlg final +{ + std::shared_ptr m_xParentDlg; + std::vector> m_RedlineParents; + std::vector> + m_RedlineChildren; + 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; + + std::unique_ptr m_xTabPagesCTRL; + std::unique_ptr m_xPopup; + 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); + 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(const std::shared_ptr& rParent, 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 : public SfxModelessDialogController +{ + std::unique_ptr m_xContentArea; + std::unique_ptr m_xImplDlg; + SwChildWinWrapper* 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 : 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 : public PanelLayout, public SfxListener +{ + std::unique_ptr mpImplDlg; + std::unique_ptr mxContentArea; +public: + SwRedlineAcceptPanel(vcl::Window* pParent, const css::uno::Reference& rFrame); + virtual ~SwRedlineAcceptPanel() override; + virtual void dispose() 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 000000000..adb2681ef --- /dev/null +++ b/sw/source/uibase/inc/regionsw.hxx @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include "condedit.hxx" +#include +#include +#include "numberingtypelistbox.hxx" +#include + +#include +#include + +class SwWrtShell; + +namespace sfx2 +{ + class DocumentInserter; + class FileDialogHelper; +} + +// dialog "edit regions" +class SectRepr; +typedef std::map> SectReprs_t; + +class SwEditRegionDlg : public SfxDialogController +{ + bool m_bSubRegionsFilled; + + SwWrtShell& rSh; + SectReprs_t m_SectReprs; + const SwSection* pCurrSect; + std::unique_ptr m_pDocInserter; + + bool bDontCheckPasswd :1; + + std::unique_ptr m_xCurName; + std::unique_ptr m_xTree; + std::unique_ptr m_xFileCB; + std::unique_ptr m_xDDECB; + std::unique_ptr m_xDDEFrame; + std::unique_ptr m_xFileNameFT; + std::unique_ptr m_xDDECommandFT; + std::unique_ptr m_xFileNameED; + std::unique_ptr m_xFilePB; + std::unique_ptr m_xSubRegionFT; + std::unique_ptr m_xSubRegionED; + std::unique_ptr m_xProtectCB; + std::unique_ptr m_xPasswdCB; + std::unique_ptr m_xPasswdPB; + std::unique_ptr m_xHideCB; + std::unique_ptr m_xConditionFT; + std::unique_ptr m_xConditionED; + // #114856# edit in readonly sections + std::unique_ptr m_xEditInReadonlyCB; + std::unique_ptr m_xOK; + std::unique_ptr m_xOptionsPB; + std::unique_ptr m_xDismiss; + std::unique_ptr 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::ToggleButton&, void ); + DECL_LINK( ChangePasswdHdl, weld::Button&, void ); + DECL_LINK( ChangeProtectHdl, weld::ToggleButton&, void ); + DECL_LINK( ChangeHideHdl, weld::ToggleButton&, void ); + // #114856# edit in readonly sections + DECL_LINK( ChangeEditInReadonlyHdl, weld::ToggleButton&, void ); + DECL_LINK( ChangeDismissHdl, weld::Button&, void); + DECL_LINK( UseFileHdl, weld::ToggleButton&, 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::ToggleButton&, void ); + DECL_LINK( DlgClosedHdl, sfx2::FileDialogHelper*, void ); + DECL_LINK( SubRegionEventHdl, weld::ComboBox&, void ); + + bool CheckPasswd(weld::ToggleButton* pBox = nullptr); + +public: + SwEditRegionDlg(weld::Window* pParent, SwWrtShell& rWrtSh); + virtual ~SwEditRegionDlg() override; + + void SelectSection(const OUString& rSectionName); + +}; + +// dialog "insert region" +class SwInsertSectionTabPage : public SfxTabPage +{ + OUString m_sFileName; + OUString m_sFilterName; + OUString m_sFilePasswd; + + css::uno::Sequence m_aNewPasswd; + SwWrtShell* m_pWrtSh; + std::unique_ptr m_pDocInserter; + + std::unique_ptr m_xCurName; + std::unique_ptr m_xFileCB; + std::unique_ptr m_xDDECB; + std::unique_ptr m_xDDECommandFT; + std::unique_ptr m_xFileNameFT; + std::unique_ptr m_xFileNameED; + std::unique_ptr m_xFilePB; + std::unique_ptr m_xSubRegionFT; + std::unique_ptr m_xSubRegionED; + std::unique_ptr m_xProtectCB; + std::unique_ptr m_xPasswdCB; + std::unique_ptr m_xPasswdPB; + std::unique_ptr m_xHideCB; + std::unique_ptr m_xConditionFT; + std::unique_ptr m_xConditionED; + // #114856# edit in readonly sections + std::unique_ptr m_xEditInReadonlyCB; + + void ChangePasswd(bool bChange); + + DECL_LINK( ChangeHideHdl, weld::ToggleButton&, void ); + DECL_LINK( ChangeProtectHdl, weld::ToggleButton&, void ); + DECL_LINK( ChangePasswdHdl, weld::Button&, void ); + DECL_LINK( TogglePasswdHdl, weld::ToggleButton&, void ); + DECL_LINK( NameEditHdl, weld::ComboBox&, void ); + DECL_LINK( UseFileHdl, weld::ToggleButton&, void ); + DECL_LINK( FileSearchHdl, weld::Button&, void ); + DECL_LINK( DDEHdl, weld::ToggleButton&, 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 Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); +}; + +class SwSectionFootnoteEndTabPage : public SfxTabPage +{ + std::unique_ptr m_xFootnoteNtAtTextEndCB; + std::unique_ptr m_xFootnoteNtNumCB; + std::unique_ptr m_xFootnoteOffsetLbl; + std::unique_ptr m_xFootnoteOffsetField; + std::unique_ptr m_xFootnoteNtNumFormatCB; + std::unique_ptr m_xFootnotePrefixFT; + std::unique_ptr m_xFootnotePrefixED; + std::unique_ptr m_xFootnoteNumViewBox; + std::unique_ptr m_xFootnoteSuffixFT; + std::unique_ptr m_xFootnoteSuffixED; + std::unique_ptr m_xEndNtAtTextEndCB; + std::unique_ptr m_xEndNtNumCB; + std::unique_ptr m_xEndOffsetLbl; + std::unique_ptr m_xEndOffsetField; + std::unique_ptr m_xEndNtNumFormatCB; + std::unique_ptr m_xEndPrefixFT; + std::unique_ptr m_xEndPrefixED; + std::unique_ptr m_xEndNumViewBox; + std::unique_ptr m_xEndSuffixFT; + std::unique_ptr m_xEndSuffixED; + + DECL_LINK(FootEndHdl, weld::ToggleButton&, 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 Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); +}; + +class SwSectionIndentTabPage : public SfxTabPage +{ + SvxParaPrevWindow m_aPreviewWin; + std::unique_ptr m_xBeforeMF; + std::unique_ptr m_xAfterMF; + std::unique_ptr 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 Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet); + + void SetWrtShell(SwWrtShell const & rSh); +}; + +class SwInsertSectionTabDialog : public SfxTabDialogController +{ + SwWrtShell& rWrtSh; + std::unique_ptr m_pSectionData; + +protected: + virtual void PageCreated(const OString& 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 : public SfxTabDialogController +{ + SwWrtShell& rWrtSh; + +protected: + virtual void PageCreated(const OString& 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 000000000..58439eb89 --- /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 + +class SwWrtShell; + +class SwTableHeightDlg : public weld::GenericDialogController +{ + SwWrtShell &m_rSh; + + std::unique_ptr m_xHeightEdit; + std::unique_ptr 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 000000000..fff22eb0d --- /dev/null +++ b/sw/source/uibase/inc/scroll.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_SCROLL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SCROLL_HXX +#include + +class SwScrollbar: public ScrollBar +{ + Size aDocSz; + bool bHori :1; // horizontal = salTrue, otherwise vertical + bool bAuto :1; // for scrolling mode + bool bVisible :1; // show/hide should only set this flag + bool bSizeSet :1; // was the size already set? + + void AutoShow(); + + using Window::Hide; + using Window::IsVisible; + +public: + void ExtendedShow( bool bVisible = true ); + void SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) override; + bool IsVisible(bool bReal) const { return bReal ? ScrollBar::IsVisible() : bVisible; } + + // changing of document size + void DocSzChgd(const Size &rNewSize); + // changing of visible region + void ViewPortChgd(const tools::Rectangle &rRectangle); + // what is it?? + bool IsHoriScroll() const { return bHori; } + + void SetAuto(bool bSet); + bool IsAuto() const { return bAuto;} + + SwScrollbar(vcl::Window *pParent, bool bHori ); + virtual ~SwScrollbar() override; +}; + +#endif + +/* 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 000000000..b31f61a54 --- /dev/null +++ b/sw/source/uibase/inc/selglos.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_SELGLOS_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SELGLOS_HXX + +#include + +class SwSelGlossaryDlg final : public weld::GenericDialogController +{ + std::unique_ptr m_xFrame; + std::unique_ptr m_xGlosBox; + + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); +public: + SwSelGlossaryDlg(weld::Window * pParent, const OUString &rShortName); + virtual ~SwSelGlossaryDlg() override; + + void InsertGlos(const OUString &rRegion, const OUString &rGlosName) + { + const OUString aTmp = 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); + } +}; + +#endif + +/* 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 000000000..138cbf51e --- /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 +#include + +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 000000000..2bd51c69c --- /dev/null +++ b/sw/source/uibase/inc/shdwcrsr.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_SHDWCRSR_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SHDWCRSR_HXX + +#include +#include +#include +#include +#include + +class SwShadowCursor +{ + VclPtr pWin; + Color aCol; + Point aOldPt; + long nOldHeight; + sal_uInt16 nOldMode; + + void DrawTri( const Point& rPt, long nHeight, bool bLeft ); + void DrawCursor( const Point& rPt, long nHeight, sal_uInt16 nMode ); + +public: + SwShadowCursor( vcl::Window& rWin, const Color& rCol ) + : pWin( &rWin ), aCol( rCol ), nOldHeight(0), nOldMode( USHRT_MAX ) {} + ~SwShadowCursor(); + + void SetPos( const Point& rPt, long nHeight, sal_uInt16 nMode ); + + void Paint(); + + tools::Rectangle GetRect() const; +}; + +#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 000000000..ac75e72c6 --- /dev/null +++ b/sw/source/uibase/inc/splittbl.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_SPLITTBL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SPLITTBL_HXX + +#include +#include + +class SwWrtShell; + +class SwSplitTableDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr m_xHorzBox; + std::unique_ptr m_xContentCopyRB; + std::unique_ptr m_xBoxAttrCopyWithParaRB; + std::unique_ptr m_xBoxAttrCopyNoParaRB; + std::unique_ptr m_xBorderCopyRB; + + SwWrtShell &rShell; + SplitTable_HeadlineOption m_nSplit; + + 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 { return m_nSplit; } +}; + +#endif + +/* 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 000000000..e48226f35 --- /dev/null +++ b/sw/source/uibase/inc/srcedtw.hxx @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + +#include +#include + +namespace com::sun::star::beans { class XMultiPropertySet; } +class ScrollBar; +class SwSrcView; +class SwSrcEditWindow; +class TextEngine; +class TextView; +class DataChangedEvent; + +class TextViewOutWin : public vcl::Window +{ + TextView* pTextView; + +protected: + 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), pTextView(nullptr){} + + void SetTextView( TextView* pView ) {pTextView = pView;} + +}; + +class SwSrcEditWindow : public vcl::Window, public SfxListener +{ +private: + class ChangesListener; + friend class ChangesListener; + std::unique_ptr m_pTextView; + std::unique_ptr m_pTextEngine; + + VclPtr m_pOutWin; + VclPtr m_pHScrollbar, + m_pVScrollbar; + + SwSrcView* m_pSrcView; + + rtl::Reference< ChangesListener > m_xListener; + osl::Mutex mutex_; + css::uno::Reference< css::beans::XMultiPropertySet > + m_xNotifier; + + long m_nCurTextWidth; + sal_uInt16 m_nStartLine; + rtl_TextEncoding m_eSourceEncoding; + bool m_bReadonly; + bool m_bHighlighting; + + Idle m_aSyntaxIdle; + std::set m_aSyntaxLineTable; + + void ImpDoHighlight( const OUString& rSource, sal_uInt16 nLineOff ); + + using OutputDevice::SetFont; + void SetFont(); + + DECL_LINK( SyntaxTimerHdl, Timer *, void ); + + using Window::Invalidate; + +protected: + + virtual void Resize() override; + virtual void DataChanged( const DataChangedEvent& ) override; + virtual void GetFocus() override; +// virtual void LoseFocus(); + + void CreateTextEngine(); + void DoSyntaxHighlight( sal_uInt16 nPara ); + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + + DECL_LINK(ScrollHdl, 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 Invalidate( InvalidateFlags nFlags = InvalidateFlags::NONE ) 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 000000000..a2e8277b9 --- /dev/null +++ b/sw/source/uibase/inc/srcview.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_SRCVIEW_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SRCVIEW_HXX + +#include +#include +#include + +#include "srcedtw.hxx" +#include + +class SwDocShell; +class SvxSearchItem; +class SfxMedium; + +class SwSrcView: public SfxViewShell +{ + VclPtr aEditWin; + + std::unique_ptr pSearchItem; + + bool bSourceSaved :1; + rtl_TextEncoding eLoadEncoding; + void Init(); + + // for read-only switching + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + +protected: + 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* pFrame, SfxViewShell*); + + virtual ~SwSrcView() override; + + SwDocShell* GetDocShell(); + void SaveContent(const OUString& rTmpFile); + void SaveContentTo(SfxMedium& rMed); + + bool IsModified() const {return 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 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 000000000..b4828dcf5 --- /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 +#include +#include + +class SwWrtShell; + +class SwSortDlg : public weld::GenericDialogController +{ + weld::Window* m_pParent; + std::unique_ptr m_xColLbl; + + std::unique_ptr m_xKeyCB1; + std::unique_ptr m_xColEdt1; + std::unique_ptr m_xTypDLB1; + std::unique_ptr m_xSortUp1RB; + std::unique_ptr m_xSortDn1RB; + + std::unique_ptr m_xKeyCB2; + std::unique_ptr m_xColEdt2; + std::unique_ptr m_xTypDLB2; + std::unique_ptr m_xSortUp2RB; + std::unique_ptr m_xSortDn2RB; + + std::unique_ptr m_xKeyCB3; + std::unique_ptr m_xColEdt3; + std::unique_ptr m_xTypDLB3; + std::unique_ptr m_xSortUp3RB; + std::unique_ptr m_xSortDn3RB; + + std::unique_ptr m_xColumnRB; + std::unique_ptr m_xRowRB; + + std::unique_ptr m_xDelimTabRB; + std::unique_ptr m_xDelimFreeRB; + std::unique_ptr m_xDelimEdt; + std::unique_ptr m_xDelimPB; + + std::unique_ptr m_xLangLB; + + std::unique_ptr m_xCaseCB; + + OUString aColText; + OUString aRowText; + OUString aNumericText; + + SwWrtShell &rSh; + std::unique_ptr m_xColRes; + + sal_uInt16 nX; + sal_uInt16 nY; + + void Apply(); + sal_Unicode GetDelimChar() const; + + DECL_LINK(CheckHdl, weld::ToggleButton&, void); + DECL_LINK(DelimHdl, weld::ToggleButton&, 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 000000000..76efc6d88 --- /dev/null +++ b/sw/source/uibase/inc/swcont.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +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, + LAST = DRAWOBJECT, + 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 nTypeId; + + public: + SwTypeNumber(sal_uInt8 nId) :nTypeId(nId){} + virtual ~SwTypeNumber(); + + sal_uInt8 GetTypeId() const { return nTypeId;} +}; + +class SwContent : public SwTypeNumber +{ + const SwContentType* pParent; + OUString sContentName; + long 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 bInvisible; +public: + SwContent(const SwContentType* pCnt, const OUString& rName, long nYPos ); + + virtual bool IsProtect() const; + const SwContentType* GetParent() const {return pParent;} + const OUString& GetName() const {return 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 (nYPosition != rCont.nYPosition) + return nYPosition < rCont.nYPosition; + return vcl::NaturalSortCompare(sContentName, rCont.sContentName) < 0; + } + + bool IsInvisible() const {return bInvisible;} + void SetInvisible(){ 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 000000000..e231269e7 --- /dev/null +++ b/sw/source/uibase/inc/swdtflvr.hxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class Graphic; +class ImageMap; +class INetBookmark; +class INetImage; +class SfxAbstractPasteDialog; +class SwDoc; +class SwDocFac; +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 : is_typed_flags {}; +} +// 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 SW_DLLPUBLIC SwTransferable : public TransferableHelper +{ + friend class SwView_Impl; + SfxObjectShellLock m_aDocShellRef; + TransferableObjectDescriptor m_aObjDesc; + tools::SvRef m_xDdeLink; + + SwWrtShell *m_pWrtShell; + /* #96392# Added pCreatorView to distinguish SwFrameShell from + SwWrtShell. */ + const SwFrameShell *m_pCreatorView; + std::unique_ptr> m_pClpDocFac; + std::unique_ptr m_pClpGraphic; + std::unique_ptr m_pClpBitmap; + Graphic *m_pOrigGraphic; + std::unique_ptr m_pBookmark; // URL and description! + std::unique_ptr m_pImageMap; + std::unique_ptr 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( TransferableDataHelper& rData, + OUString& rFileName, OUString* pTitle = nullptr ); + static bool TestAllowedFormat( const TransferableDataHelper& rData, + SotClipboardFormatId nFormat, SotExchangeDest nDestination ); + + static bool PasteFileContent( 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( TransferableDataHelper& rData, SwWrtShell& rSh, + SwPasteSdr nAction, const Point* pPt, bool bInsertGRF ); + + static bool PasteDDE( TransferableDataHelper& rData, SwWrtShell& rWrtShell, + bool bReReadGrf, bool bMsg ); + + static bool PasteSdrFormat( TransferableDataHelper& rData, + SwWrtShell& rSh, SwPasteSdr nAction, + const Point* pPt, SotExchangeActionFlags nActionFlags, bool bNeedToSelectBeforePaste); + + static bool PasteGrf( 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( TransferableDataHelper& rData, + SwWrtShell& rSh ); + + static bool PasteAsHyperlink( 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( TransferableDataHelper& rData, SwWrtShell& rSh, + SotClipboardFormatId nFormat, bool bLink, const Point* pDragPt, + bool bMsg ); + + static bool PasteFileList( TransferableDataHelper& rData, + SwWrtShell& rSh, bool bLink, + const Point* pPt, bool bMsg ); + + bool PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove, + bool bIsXSelection ); + + 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; + +protected: + virtual void AddSupportedFormats() override; + virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override; + virtual bool WriteObject( tools::SvRef& 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 CalculateAndCopy(); // special for Calculator + bool CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr ); + + // remove the DDE-Link format promise + void RemoveDDELinkFormat( const vcl::Window& rWin ); + + // 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& 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; } + + // Interfaces for Selection + /* #96392# Added pCreator to distinguish SwFrameShell from SwWrtShell. */ + static void CreateSelection( SwWrtShell & rSh, + const SwFrameShell * pCreator = nullptr ); + static void ClearSelection( SwWrtShell& rSh, + const SwFrameShell * pCreator = nullptr ); + + // the related SwView is being closed and the SwTransferable is invalid now + void Invalidate() {m_pWrtShell = nullptr;} + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override; + + 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 000000000..0c95e5e6a --- /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 + +class SwMessageAndEditDialog : public weld::MessageDialogController +{ +protected: + std::unique_ptr m_xEdit; + std::unique_ptr m_xOKPB; +public: + SwMessageAndEditDialog(weld::Window* pParent, const OString& 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 000000000..5c5450d53 --- /dev/null +++ b/sw/source/uibase/inc/swmodalredlineacceptdlg.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_SWMODALREDLINEACCEPTDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SWMODALREDLINEACCEPTDLG_HXX + +#include + +class SwRedlineAcceptDlg; + +class SwModalRedlineAcceptDlg : public SfxDialogController +{ + std::unique_ptr m_xContentArea; + std::unique_ptr m_xImplDlg; + +public: + SwModalRedlineAcceptDlg(weld::Window *pParent); + virtual ~SwModalRedlineAcceptDlg() override; + + void AcceptAll( bool bAccept ); + virtual void Activate() override; +}; + +#endif + +/* 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 000000000..b4540857e --- /dev/null +++ b/sw/source/uibase/inc/swrenamexnameddlg.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_SWRENAMEXNAMEDDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SWRENAMEXNAMEDDLG_HXX + +#include +#include +#include +#include + +class SwRenameXNamedDlg : public weld::GenericDialogController +{ + css::uno::Reference< css::container::XNamed > & xNamed; + css::uno::Reference< css::container::XNameAccess > & xNameAccess; + css::uno::Reference< css::container::XNameAccess > xSecondAccess; + css::uno::Reference< css::container::XNameAccess > xThirdAccess; + + TextFilter m_aTextFilter; + + std::unique_ptr m_xNewNameED; + std::unique_ptr m_xOk; + + DECL_LINK(TextFilterHdl, OUString&, bool); + DECL_LINK(OkHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, weld::Entry&, void); + +public: + SwRenameXNamedDlg(weld::Window* 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 ) + { + xSecondAccess = xSecond; + xThirdAccess = xThird; + } +}; + +#endif + +/* 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 000000000..2dac3e6c7 --- /dev/null +++ b/sw/source/uibase/inc/swruler.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include + +class SwViewShell; +class View; +namespace vcl { class Window; } +class SwEditWin; + +/** + * 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; + std::string CreateJsonNotification(); + +private: + SwViewShell * mpViewShell; //< Shell to check if there is any comments on doc and their visibility + VclPtr 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 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 000000000..82f9fb92b --- /dev/null +++ b/sw/source/uibase/inc/swtablerep.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_SWTABLEREP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SWTABLEREP_HXX + +#include +#include +#include + +class SwTabCols; +struct TColumn; +class SW_DLLPUBLIC SwTableRep +{ + std::unique_ptr m_pTColumns; + + 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(); + + 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() const {return m_pTColumns.get();} +}; +#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 000000000..4e0f5c2b2 --- /dev/null +++ b/sw/source/uibase/inc/swuiccoll.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_SWUICCOLL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_SWUICCOLL_HXX + +#include + +#include + +class SwWrtShell; +class SwFormat; + +class SwCondCollPage : public SfxTabPage +{ + std::vector m_aStrArr; + + SwWrtShell &m_rSh; + const CommandStruct*m_pCmds; + SwFormat* m_pFormat; + + bool m_bNewTemplate; + + std::unique_ptr m_xConditionCB; + std::unique_ptr m_xTbLinks; + std::unique_ptr m_xStyleLB; + std::unique_ptr m_xFilterLB; + std::unique_ptr m_xRemovePB; + std::unique_ptr m_xAssignPB; + + virtual DeactivateRC DeactivatePage(SfxItemSet *pSet) override; + + DECL_LINK(OnOffHdl, weld::ToggleButton&, void); + 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 sal_uInt16 m_aPageRg[]; + +public: + SwCondCollPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + virtual ~SwCondCollPage() override; + + static std::unique_ptr Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet); + static const sal_uInt16* GetRanges() { return m_aPageRg; } + + virtual bool FillItemSet( SfxItemSet *rSet) override; + virtual void Reset (const SfxItemSet *rSet) override; + + void SetCollection( SwFormat* pFormat, bool bNew ); +}; + +#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 000000000..1628cf225 --- /dev/null +++ b/sw/source/uibase/inc/swuicnttab.hxx @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + +#include +#include "toxmgr.hxx" +#include "cnttab.hxx" +#include + +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 : public SfxTabDialogController +{ + std::unique_ptr m_pMgr; + SwWrtShell& m_rWrtShell; + + struct TypeData + { + std::unique_ptr m_pForm; + std::unique_ptr m_pDescription; + std::unique_ptr m_pxIndexSections; + }; + std::vector 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 m_xExampleFrame; + std::unique_ptr m_xShowExampleCB; + std::unique_ptr m_xExampleFrameWin; + + virtual short Ok() override; + std::unique_ptr CreateTOXDescFromTOXBase(const SwTOXBase*pCurTOX); + + DECL_LINK(CreateExample_Hdl, SwOneExampleFrame&, void); + DECL_LINK(ShowPreviewHdl, weld::ToggleButton&, void); + +public: + SwMultiTOXTabDialog(weld::Window* pParent, const SfxItemSet& rSet, + SwWrtShell &rShell, + SwTOXBase* pCurTOX, sal_uInt16 nToxType, + bool bGlobal); + virtual ~SwMultiTOXTabDialog() override; + + virtual void PageCreated(const OString& 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 : public SfxTabPage +{ + std::unique_ptr pIndexRes; + + OUString aStyleArr[MAXLEVEL]; + OUString sAutoMarkURL; + OUString sAutoMarkType; + OUString sAddStyleUser; + OUString sAddStyleContent; + + std::unique_ptr pIndexEntryWrapper; + + bool m_bWaitingInitialSettings; + + std::unique_ptr m_xTitleED; + std::unique_ptr m_xTypeFT; + std::unique_ptr m_xTypeLB; + std::unique_ptr m_xReadOnlyCB; + + std::unique_ptr m_xAreaFrame; + std::unique_ptr m_xAreaLB; + std::unique_ptr m_xLevelFT; //content, user + std::unique_ptr m_xLevelNF; //content, user + + //content + std::unique_ptr m_xCreateFrame; // content, user, illustration + std::unique_ptr m_xFromHeadingsCB; + std::unique_ptr m_xStylesCB; + std::unique_ptr m_xAddStylesCB; + std::unique_ptr m_xAddStylesPB; + //user + std::unique_ptr m_xFromTablesCB; + std::unique_ptr m_xFromFramesCB; + std::unique_ptr m_xFromGraphicsCB; + std::unique_ptr m_xFromOLECB; + std::unique_ptr m_xLevelFromChapterCB; + + //illustration + table + std::unique_ptr m_xFromCaptionsRB; + std::unique_ptr m_xFromObjectNamesRB; + + //illustration and tables + std::unique_ptr m_xCaptionSequenceFT; + std::unique_ptr m_xCaptionSequenceLB; + std::unique_ptr m_xDisplayTypeFT; + std::unique_ptr m_xDisplayTypeLB; + + //all but illustration and table + std::unique_ptr m_xTOXMarksCB; + + //index only + std::unique_ptr m_xIdxOptionsFrame; + std::unique_ptr m_xCollectSameCB; + std::unique_ptr m_xUseFFCB; + std::unique_ptr m_xUseDashCB; + std::unique_ptr m_xCaseSensitiveCB; + std::unique_ptr m_xInitialCapsCB; + std::unique_ptr m_xKeyAsEntryCB; + std::unique_ptr m_xFromFileCB; + std::unique_ptr m_xAutoMarkPB; + + // object only + std::unique_ptr m_xFromObjCLB; + std::unique_ptr m_xFromObjFrame; + + std::unique_ptr m_xSequenceCB; + std::unique_ptr m_xBracketLB; + std::unique_ptr m_xAuthorityFrame; + + //all + std::unique_ptr m_xSortFrame; + std::unique_ptr m_xLanguageLB; + std::unique_ptr m_xSortAlgorithmLB; + + DECL_LINK(TOXTypeHdl, weld::ComboBox&, void ); + DECL_LINK(AddStylesHdl, weld::Button&, void ); + DECL_LINK(MenuEnableHdl, weld::ToggleButton&, void); + DECL_LINK(MenuExecuteHdl, const OString&, void); + DECL_LINK(LanguageListBoxHdl, weld::ComboBox&, void); + void LanguageHdl(const weld::ComboBox*); + DECL_LINK(CheckBoxHdl, weld::ToggleButton&, void ); + DECL_LINK(RadioButtonHdl, weld::ToggleButton&, 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 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 m_aButtonSelectedHdl; + SwTOXWidget* m_pActiveCtrl; + Link m_aModifyHdl; + OUString m_sAccessibleName; + OUString m_sAdditionalAccnameString1; + OUString m_sAdditionalAccnameString2; + OUString m_sAdditionalAccnameString3; + + Idle m_aAdjustPositionsIdle; + + SwTOXEntryTabPage* m_pParent; + std::unique_ptr m_xParentWidget; + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; + std::unique_ptr m_xLeftScrollWin; + std::unique_ptr m_xCtrlParentWin; + std::unique_ptr m_xScrollWin; + std::unique_ptr m_xRightScrollWin; + std::vector> 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(long nOffset); + +public: + SwTokenWindow(std::unique_ptr 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& rLink) + { m_aButtonSelectedHdl = rLink;} + + void SetModifyHdl(const Link& 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 : public SfxTabPage +{ + OUString sDelimStr; + OUString sLevelStr; + OUString sAuthTypeStr; + + OUString sNoCharStyle; + SwForm* m_pCurrentForm; + + CurTOXType aLastTOXType; + bool bInLevelHdl; + + std::unique_ptr m_xTypeFT; + std::unique_ptr m_xLevelFT; + std::unique_ptr m_xLevelLB; + std::unique_ptr m_xAllLevelsPB; + std::unique_ptr m_xEntryNoPB; + std::unique_ptr m_xEntryPB; + std::unique_ptr m_xTabPB; + std::unique_ptr m_xChapterInfoPB; + std::unique_ptr m_xPageNoPB; + std::unique_ptr m_xHyperLinkPB; + std::unique_ptr m_xAuthFieldsLB; + std::unique_ptr m_xAuthInsertPB; + std::unique_ptr m_xAuthRemovePB; + std::unique_ptr m_xCharStyleLB; // character style of the current token + std::unique_ptr m_xEditStylePB; + std::unique_ptr m_xChapterEntryFT; + std::unique_ptr m_xChapterEntryLB; // type of chapter info + std::unique_ptr m_xNumberFormatFT; + std::unique_ptr m_xNumberFormatLB; //!< format for numbering (E#) + std::unique_ptr m_xEntryOutlineLevelFT; //!< Fixed text, for i53420 + std::unique_ptr m_xEntryOutlineLevelNF; //!< level to evaluate outline level to, for i53420 + std::unique_ptr m_xFillCharFT; + std::unique_ptr m_xFillCharCB; // fill char for tab stop + std::unique_ptr m_xTabPosFT; + std::unique_ptr m_xTabPosMF; // tab stop position + std::unique_ptr m_xAutoRightCB; + std::unique_ptr m_xFormatFrame; + std::unique_ptr m_xMainEntryStyleFT; + std::unique_ptr m_xMainEntryStyleLB; // character style of main entries in indexes + std::unique_ptr m_xAlphaDelimCB; + std::unique_ptr m_xCommaSeparatedCB; + std::unique_ptr m_xRelToStyleCB; // position relative to the right margin of the para style + std::unique_ptr m_xSortingFrame; + std::unique_ptr m_xSortDocPosRB; + std::unique_ptr m_xSortContentRB; + std::unique_ptr m_xSortKeyFrame; + std::unique_ptr m_xFirstKeyLB; + std::unique_ptr m_xFirstSortUpRB; + std::unique_ptr m_xFirstSortDownRB; + std::unique_ptr m_xSecondKeyLB; + std::unique_ptr m_xSecondSortUpRB; + std::unique_ptr m_xSecondSortDownRB; + std::unique_ptr m_xThirdKeyLB; + std::unique_ptr m_xThirdSortUpRB; + std::unique_ptr m_xThirdSortDownRB; + std::unique_ptr 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::ToggleButton&, 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::ToggleButton&, void); + DECL_LINK(ChapterInfoHdl, weld::ComboBox&, void); + DECL_LINK(ChapterInfoOutlineHdl, weld::SpinButton&, void); + DECL_LINK(NumberFormatHdl, weld::ComboBox&, void); + + DECL_LINK(AllLevelsHdl, weld::Button&, void); + + void WriteBackLevel(); + void UpdateDescriptor(); + DECL_LINK(ModifyHdl, LinkParamNone*, void); + void OnModify(bool bAllLevels); + DECL_LINK(ModifyClickHdl, weld::ToggleButton&, void); + +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 Create( weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rAttrSet); + void SetWrtShell(SwWrtShell& rSh); + + void PreTokenButtonRemoved(const SwFormToken& rToken); + void SetFocus2theAllBtn(); +}; + +class SwTOXStylesTabPage : public SfxTabPage +{ + std::unique_ptr m_pCurrentForm; + + std::unique_ptr m_xLevelLB; + std::unique_ptr m_xAssignBT; + std::unique_ptr m_xParaLayLB; + std::unique_ptr m_xStdBT; + std::unique_ptr 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(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 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 000000000..2bd2fb4e4 --- /dev/null +++ b/sw/source/uibase/inc/swuiidxmrk.hxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +class SwWrtShell; +class SwTOXMgr; +class SwTOXMark; + +// insert mark for index entry +class SwIndexMarkFloatDlg; +class SwIndexMarkModalDlg; + +class SwIndexMarkPane +{ + std::shared_ptr 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 + m_pTOXMgr; + SwWrtShell* m_pSh; + + std::unique_ptr m_xTypeFT; + std::unique_ptr m_xTypeDCB; + std::unique_ptr m_xNewBT; + std::unique_ptr m_xEntryED; + std::unique_ptr m_xSyncED; + std::unique_ptr m_xPhoneticFT0; + std::unique_ptr m_xPhoneticED0; + std::unique_ptr m_xKey1FT; + std::unique_ptr m_xKey1DCB; + std::unique_ptr m_xPhoneticFT1; + std::unique_ptr m_xPhoneticED1; + std::unique_ptr m_xKey2FT; + std::unique_ptr m_xKey2DCB; + std::unique_ptr m_xPhoneticFT2; + std::unique_ptr m_xPhoneticED2; + std::unique_ptr m_xLevelFT; + std::unique_ptr m_xLevelNF; + std::unique_ptr m_xMainEntryCB; + std::unique_ptr m_xApplyToAllCB; + std::unique_ptr m_xSearchCaseSensitiveCB; + std::unique_ptr m_xSearchCaseWordOnlyCB; + std::unique_ptr m_xOKBT; + std::unique_ptr m_xCloseBT; + std::unique_ptr m_xDelBT; + std::unique_ptr m_xPrevSameBT; + std::unique_ptr m_xNextSameBT; + std::unique_ptr m_xPrevBT; + std::unique_ptr m_xNextBT; + + 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::ToggleButton&, 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(const std::shared_ptr& rDialog, weld::Builder& rBuilder, + bool bNewDlg, SwWrtShell& rWrtShell); + + ~SwIndexMarkPane(); + + void ReInitDlg(SwWrtShell& rWrtShell, SwTOXMark const * pCurTOXMark = nullptr); + bool IsTOXType(const OUString& rName) { return m_xTypeDCB->find_text(rName) != -1; } +}; + +class SwIndexMarkFloatDlg : 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 : 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 bIsFromComponent; + + friend class SwAuthMarkModalDlg; + friend class SwAuthMarkFloatDlg; + + bool bNewEntry; + bool bBibAccessInitialized; + + SwWrtShell* 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 > xBibAccess; + + std::unique_ptr m_xFromComponentRB; + std::unique_ptr m_xFromDocContentRB; + std::unique_ptr m_xAuthorFI; + std::unique_ptr m_xTitleFI; + std::unique_ptr m_xEntryED; + std::unique_ptr m_xEntryLB; + std::unique_ptr m_xActionBT; + std::unique_ptr m_xCloseBT; + std::unique_ptr m_xCreateEntryPB; + std::unique_ptr 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::ToggleButton&, 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 : 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 : 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 000000000..bd282a470 --- /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 + +#include + +class SwParaDlg: public SfxTabDialogController +{ + SwView& rView; + bool bDrawParaDlg; + + void PageCreated(const OString& rId, SfxTabPage& rPage) override; + +public: + SwParaDlg(weld::Window *pParent, + SwView& rVw, + const SfxItemSet&, + sal_uInt8 nDialogMode, + const OUString *pCollName, + bool bDraw = false, + const OString& sDefPage = OString()); + 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 000000000..45be074db --- /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 +#include + +class SwWrtShell; + +class SW_DLLPUBLIC SwWrtShellItem: public SfxPoolItem +{ + SwWrtShell* pWrtSh; + +public: + SwWrtShellItem( SwWrtShell* pWrtSh ); + + virtual bool operator==( const SfxPoolItem& ) const override; + virtual SwWrtShellItem* Clone( SfxItemPool *pPool = nullptr ) const override; + + SwWrtShell* GetValue() const { return 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 000000000..43ae7ac43 --- /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 +#include + +class SwSyncBtnDlg : public SfxModelessDialogController +{ + std::unique_ptr m_xSyncBtn; + + DECL_STATIC_LINK( SwSyncBtnDlg, BtnHdl, weld::Button&, void ); + +public: + SwSyncBtnDlg(SfxBindings*, SfxChildWindow*, weld::Window *pParent); + virtual ~SwSyncBtnDlg() override; +}; + +class SwSyncChildWin : 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 000000000..3d4af57d8 --- /dev/null +++ b/sw/source/uibase/inc/tabledlg.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_TABLEDLG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_TABLEDLG_HXX + +#include + +class SwWrtShell; +struct TColumn; + +// table dialog +class SwTableTabDlg : public SfxTabDialogController +{ + SwWrtShell* pShell; + + virtual void PageCreated(const OString& 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 000000000..227ac0744 --- /dev/null +++ b/sw/source/uibase/inc/tablemgr.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include + +class SwFrameFormat; +class SwWrtShell; +namespace vcl { class Window; } +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 *pFormat; + SwWrtShell *pSh; + SwTabCols 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 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 000000000..c29d822a7 --- /dev/null +++ b/sw/source/uibase/inc/tabsh.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_TABSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_TABSH_HXX + +#include "basesh.hxx" +#include + +class SfxItemSet; +class SwWrtShell; + +SW_DLLPUBLIC void ItemSetToTableParam( const SfxItemSet& rSet, SwWrtShell &rSh ); + +SW_DLLPUBLIC const sal_uInt16* 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 000000000..8438e5701 --- /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 +#include +#include +#include +#include + +#include "wrtsh.hxx" +#include "autoformatpreview.hxx" +#include + +class SwTableAutoFormat; +class SwTableAutoFormatTable; +class SwWrtShell; + +class SwAutoFormatDlg : 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 m_xTableTable; + + std::unique_ptr m_xLbFormat; + std::unique_ptr m_xBtnNumFormat; + std::unique_ptr m_xBtnBorder; + std::unique_ptr m_xBtnFont; + std::unique_ptr m_xBtnPattern; + std::unique_ptr m_xBtnAlignment; + std::unique_ptr m_xBtnCancel; + std::unique_ptr m_xBtnAdd; + std::unique_ptr m_xBtnRemove; + std::unique_ptr m_xBtnRename; + std::unique_ptr m_xWndPreview; + + void Init( const SwTableAutoFormat* pSelFormat ); + void UpdateChecks( const SwTableAutoFormat&, bool bEnableBtn ); + + DECL_LINK(CheckHdl, weld::ToggleButton&, 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 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 000000000..300688b92 --- /dev/null +++ b/sw/source/uibase/inc/tblnumfm.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_TBLNUMFM_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_TBLNUMFM_HXX + +#include + +namespace weld { class Window; } +class SfxItemSet; + +class SwNumFormatDlg : public SfxSingleTabDialogController +{ +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 000000000..849bffcf4 --- /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 +#include + +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_LINK( RedlineNextHdl, AbstractSvxPostItDialog&, void ); + DECL_LINK( RedlinePrevHdl, AbstractSvxPostItDialog&, void ); + DECL_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 000000000..2679c0017 --- /dev/null +++ b/sw/source/uibase/inc/titlepage.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/. + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_TITLEPAGE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_TITLEPAGE_HXX + +#include + +#include + +namespace vcl { class Window; } +class SwWrtShell; +class SwPageDesc; + +class SwTitlePageDlg : public SfxDialogController +{ +private: + SwWrtShell *mpSh; + + std::unique_ptr mpPageFormatDesc; + + SwPageDesc *mpTitleDesc; + const SwPageDesc *mpIndexDesc; + const SwPageDesc *mpNormalDesc; + + std::unique_ptr m_xUseExistingPagesRB; + std::unique_ptr m_xPageCountNF; + std::unique_ptr m_xDocumentStartRB; + std::unique_ptr m_xPageStartRB; + std::unique_ptr m_xPageStartNF; + std::unique_ptr m_xRestartNumberingCB; + std::unique_ptr m_xRestartNumberingNF; + std::unique_ptr m_xSetPageNumberCB; + std::unique_ptr m_xSetPageNumberNF; + std::unique_ptr m_xPagePropertiesLB; + std::unique_ptr m_xPagePropertiesPB; + std::unique_ptr m_xOkPB; + + void FillList(); + + sal_uInt16 GetInsertPosition() const; + + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(EditHdl, weld::Button&, void); + DECL_LINK(RestartNumberingHdl, weld::ToggleButton&, void); + DECL_LINK(SetPageNumberHdl, weld::ToggleButton&, void); + DECL_LINK(ValueChangeHdl, weld::SpinButton&, void); + DECL_LINK(StartPageHdl, weld::ToggleButton&, 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 000000000..95682aaa0 --- /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 +#include + +class SfxItemSet; +class SwWrtShell; + +// the tab dialog carrier of TabPages +class SwTemplateDlgController : public SfxStyleDialogController +{ + + SfxStyleFamily nType; + sal_uInt16 nHtmlMode; + SwWrtShell* pWrtShell; + bool bNewStyle; + +public: + /// @param sPage + /// Identifies name of page to open at by default + SwTemplateDlgController(weld::Window* pParent, + SfxStyleSheetBase& rBase, + SfxStyleFamily nRegion, + const OString& sPage, + SwWrtShell* pActShell, + bool bNew); + + virtual void RefreshInputSet() override; + + virtual void PageCreated(const OString& 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 000000000..80fa0fa61 --- /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 + +class SwTemplateControl : public SfxStatusBarControl +{ +protected: + virtual void Command( const CommandEvent& rCEvt ) override; +public: + virtual void StateChanged( 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 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 000000000..057181f60 --- /dev/null +++ b/sw/source/uibase/inc/toxmgr.hxx @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include + +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 + m_aTitle; + std::optional + m_aTOUName; + std::unique_ptr + 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 const & GetTitle() const {return m_aTitle; } + + void SetTOUName(const OUString& rSet) { m_aTOUName = rSet; } + std::optional 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 maPrimKey; + std::optional maSecKey; + std::optional maAltStr; + std::optional maTOUName; + + std::optional maPhoneticReadingOfAltStr; + std::optional maPhoneticReadingOfPrimKey; + std::optional 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 const & GetPrimKey() const { return maPrimKey; } + + void SetSecKey(const OUString& rSet) { maSecKey = rSet; } + std::optional const & GetSecKey() const { return maSecKey; } + + void SetAltStr(const OUString& rSet) { maAltStr = rSet; } + std::optional const & GetAltStr() const { return maAltStr; } + + void SetTOUName(const OUString& rSet) { maTOUName = rSet; } + std::optional const & GetTOUName() const { return maTOUName; } + + void SetPhoneticReadingOfAltStr(const OUString& rSet) { maPhoneticReadingOfAltStr = rSet; } + std::optional const & GetPhoneticReadingOfAltStr() const { return maPhoneticReadingOfAltStr; } + + void SetPhoneticReadingOfPrimKey(const OUString& rSet) { maPhoneticReadingOfPrimKey = rSet; } + std::optional const & GetPhoneticReadingOfPrimKey() const { return maPhoneticReadingOfPrimKey; } + + void SetPhoneticReadingOfSecKey(const OUString& rSet) { maPhoneticReadingOfSecKey = rSet; } + std::optional const & GetPhoneticReadingOfSecKey() const { return maPhoneticReadingOfSecKey; } +}; + +class SW_DLLPUBLIC SwTOXMgr +{ + SwWrtShell* pSh; + SwTOXMark* pCurTOXMark; + SwTOXMarks 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 pSh; } +}; + +// inlines +inline sal_uInt16 SwTOXMgr::GetTOXMarkCount() const + { return aCurMarks.size(); } + +inline SwTOXMark* SwTOXMgr::GetCurTOXMark() + { return pCurTOXMark; } + +#endif + +/* 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 000000000..f3764ad9f --- /dev/null +++ b/sw/source/uibase/inc/uiborder.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_UIBORDER_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_UIBORDER_HXX + +#include +#include + +class SwBorderDlg : public SfxSingleTabDialogController +{ +public: + + // nType may be: + // SW_BORDER_MODE_PARA + // SW_BORDER_MODE_TABLE + // SW_BORDER_MODE_FRAME + + SwBorderDlg(weld::Window* pParent, 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 000000000..629013cf3 --- /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 +#include +#include +#include + +class SwNumRule; +class IntlWrapper; +class SwPaM; + +// container for FootNote +class SW_DLLPUBLIC SwPageFootnoteInfoItem : public SfxPoolItem +{ + SwPageFootnoteInfo 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 aFootnoteInfo; } + const SwPageFootnoteInfo& GetPageFootnoteInfo() const { return aFootnoteInfo; } +}; + +class SW_DLLPUBLIC SwPtrItem : public SfxPoolItem +{ + void* 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 pMisc; } +}; + +class SW_DLLPUBLIC SwUINumRuleItem : public SfxPoolItem +{ + std::unique_ptr 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 pRule.get(); } + SwNumRule* GetNumRule() { return pRule.get(); } +}; + +class SwPaMItem : 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 000000000..7da897aa5 --- /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 +#include + +#include +#include + +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 aFormat; + OUString sCharFormatName; + sal_uInt16 nCharPoolId; + std::vector> m_Items; + + SwNumFormatGlobal& operator=( const SwNumFormatGlobal& ) = delete; + + public: + SwNumFormatGlobal( const SwNumFormat& rFormat ); + SwNumFormatGlobal( const SwNumFormatGlobal& ); + ~SwNumFormatGlobal(); + + SwNumFormat MakeNumFormat(SwWrtShell& rSh) const; + }; + + std::unique_ptr 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 &, const OUString &); + SwNumRulesWithName( const SwNumRulesWithName & ); + ~SwNumRulesWithName(); + + SwNumRulesWithName &operator=(const SwNumRulesWithName &); + + const OUString& GetName() const { return maName; } + std::unique_ptr MakeNumRule(SwWrtShell& rSh) 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 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 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 000000000..97362b51a --- /dev/null +++ b/sw/source/uibase/inc/uiobject.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 SW_SOURCE_UIBASE_INC_UIOBJECT_HXX +#define SW_SOURCE_UIBASE_INC_UIOBJECT_HXX + +#include +#include + +#include "edtwin.hxx" +#include "navipi.hxx" + +class SwEditWinUIObject : public WindowUIObject +{ +public: + + SwEditWinUIObject(const VclPtr& xEditWin); + + virtual StringMap get_state() override; + + virtual void execute(const OUString& rAction, + const StringMap& rParameters) override; + + static std::unique_ptr create(vcl::Window* pWindow); + +protected: + + virtual OUString get_name() const override; + +private: + + VclPtr mxEditWin; + +}; + +class SwNavigationPIUIObject : public WindowUIObject +{ + VclPtr mxSwNavigationPI; + +public: + + SwNavigationPIUIObject(const VclPtr& xSwNavigationPI); + + virtual StringMap get_state() override; + + virtual void execute(const OUString& rAction, + const StringMap& rParameters) override; + + static std::unique_ptr create(vcl::Window* pWindow); + +protected: + + OUString get_name() const override; +}; + + +#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 000000000..ac782d806 --- /dev/null +++ b/sw/source/uibase/inc/uitool.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_UITOOL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_UITOOL_HXX + +#include +#include +#include +#include + +class SfxItemSet; +class SwPageDesc; +class SvxTabStopItem; +class SwWrtShell; +class ListBox; +namespace weld { class ComboBox; } +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 +**/ +SW_DLLPUBLIC void ConvertAttrCharToGen(SfxItemSet& rSet); + +/** + * 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 +**/ +SW_DLLPUBLIC void ConvertAttrGenToChar(SfxItemSet& rSet, const SfxItemSet& rOrigSet); + + +/** +* 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(const Color& rBackgroundColor, 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( PopupMenu const & rMenu, SfxViewFrame const & 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 000000000..ae9f3d7b3 --- /dev/null +++ b/sw/source/uibase/inc/uivwimp.hxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include + +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 : public ::cppu::WeakImplHelper< + css::lang::XEventListener > +{ + SwView* pView; + +public: + + SwScannerEventListener( SwView& rView ) : pView( &rView ) {} + virtual ~SwScannerEventListener() override; + + // XEventListener + virtual void SAL_CALL disposing( + const css::lang::EventObject& rEventObject ) override; + + void ViewDestroyed() { pView = nullptr; } +}; + +// Clipboard EventListener +class SwClipboardChangeListener : public ::cppu::WeakImplHelper< + css::datatransfer::clipboard::XClipboardListener > +{ + SwView* 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 ) : pView( &rView ) {} + virtual ~SwClipboardChangeListener() override; + + void ViewDestroyed() { pView = nullptr; } + + void AddRemoveListener( bool bAdd ); +}; + +class SwMailMergeConfigItem; + +class SwView_Impl +{ + css::uno::Reference< css::frame::XDispatchProviderInterceptor > xDisProvInterceptor; + css::uno::Reference< css::view::XSelectionSupplier > mxXTextView; // UNO object + std::vector< css::uno::WeakReference< css::lang::XUnoTunnel > > mxTransferables; + + // temporary document for printing text of selection / multi selection + // in PDF export. + SfxObjectShellLock xTmpSelDocSh; + + SwView* pView; + rtl::Reference + mxScanEvtLstnr; + rtl::Reference + mxClipEvtLstnr; + ShellMode eShellMode; + + std::shared_ptr + xConfigItem; + + std::unique_ptr m_pDocInserter; + std::unique_ptr m_pRequest; + sal_Int16 m_nParam; + + Point m_aEditingPosition; + bool m_bSelectObject; + bool m_bEditingPositionSet; + +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 eShellMode;} + + void ExecuteScan(SfxRequest& rReq); + SwScannerEventListener& GetScannerEventListener(); + + void AddClipboardListener(); + + void AddTransferable(SwTransferable& rTransferable); + + void SetMailMergeConfigItem(std::shared_ptr const & rItem) + { + xConfigItem = rItem; + } + std::shared_ptr const & GetMailMergeConfigItem() const {return 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& rEndDialogHdl, + const sal_uInt16 nSlotId + ); + std::unique_ptr 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 000000000..dba379b2c --- /dev/null +++ b/sw/source/uibase/inc/unoatxt.hxx @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SwTextBlocks; +class SwGlossaries; +class SwDoc; +class SwDocShell; +class SwXBodyText; + +#ifndef SW_DECL_SWDOCSHELL_DEFINED +#define SW_DECL_SWDOCSHELL_DEFINED +#include +typedef tools::SvRef SwDocShellRef; +#endif + +class SwXAutoTextContainer : public cppu::WeakImplHelper +< + css::text::XAutoTextContainer2, + css::lang::XServiceInfo +> +{ + SwGlossaries *pGlossaries; + +protected: + 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 : public cppu::WeakImplHelper +< + css::text::XAutoTextGroup, + css::beans::XPropertySet, + css::lang::XServiceInfo, + css::container::XIndexAccess, + css::container::XNamed, + css::lang::XUnoTunnel +> +{ + const SfxItemPropertySet* pPropSet; + SwGlossaries* pGlossaries; + OUString sName; + OUString m_sGroupName; // prefix m_ to disambiguate from some local vars in the implementation + +protected: + virtual ~SwXAutoTextGroup() override; // ref-counted objects are not to be deleted from outside -> protected dtor + +public: + SwXAutoTextGroup(const OUString& rName, SwGlossaries* pGloss); + + static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId(); + + //XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + //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 cppu::BaseMutex + ,public cppu::WeakComponentImplHelper + < + css::text::XAutoTextEntry, + css::lang::XServiceInfo, + css::lang::XUnoTunnel, + css::text::XText, + css::document::XEventsSupplier + > +{ + SwGlossaries* pGlossaries; + OUString sGroupName; + OUString sEntryName; + SwDocShellRef xDocSh; + rtl::Reference + mxBodyText; + + void EnsureBodyText () + { + if ( !mxBodyText.is() ) + GetBodyText(); + } + void GetBodyText (); + + void SAL_CALL disposing() override; + + /** ensure that the current content (which may only be in-memory so far) is flushed to the auto text group file + +

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.
+ So we need to ensure that before somebody else does something with our auto text, we flush our + (in-memory) copy to disk.

+ + */ + 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* , const OUString& rGroupName, const OUString& rEntryName); + + static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId(); + + //XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + //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() {pGlossaries = nullptr;} + const SwGlossaries* GetGlossaries() const { return pGlossaries; } + const OUString& GetGroupName() const {return sGroupName;} + const OUString& GetEntryName() const {return sEntryName;} +}; + +/** Implement the XNameAccess for the AutoText events */ +class SwAutoTextEventDescriptor : public SvBaseEventDescriptor +{ + SwXAutoTextEntry& rAutoTextEntry; + + using SvBaseEventDescriptor::replaceByName; + using SvBaseEventDescriptor::getByName; + +public: + SwAutoTextEventDescriptor( SwXAutoTextEntry& rAutoText ); + + virtual ~SwAutoTextEventDescriptor() override; + + virtual OUString SAL_CALL getImplementationName() override; + +protected: + + 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 000000000..316bcf015 --- /dev/null +++ b/sw/source/uibase/inc/unodispatch.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include + +class SwView; + +class SwXDispatchProviderInterceptor : public cppu::WeakImplHelper +< + css::frame::XDispatchProviderInterceptor, + css::lang::XEventListener, + css::lang::XUnoTunnel, + 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; + + //XUnoTunnel + static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId(); + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + // XInterceptorInfo + virtual css::uno::Sequence SAL_CALL getInterceptedURLs() override; + + // view destroyed + void Invalidate(); +}; + +struct StatusStruct_Impl +{ + css::uno::Reference< css::frame::XStatusListener> xListener; + css::util::URL aURL; +}; +class SwXDispatch : 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 000000000..2b35f7cd3 --- /dev/null +++ b/sw/source/uibase/inc/unomailmerge.hxx @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 cppu::OMultiTypeInterfaceContainerHelperVar + OPropertyListenerContainerHelper; + +class SwDBManager; +class MailMergeExecuteFinalizer; + +class SwXMailMerge : + 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::OInterfaceContainerHelper2 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; +protected: + 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 000000000..1bd195689 --- /dev/null +++ b/sw/source/uibase/inc/unomod.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_UNOMOD_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOMOD_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +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 : 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; + +protected: + 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() + throw() 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; +}; + +class SwXViewSettings final : public comphelper::ChainablePropertySet +{ + friend class SwXDocumentSettings; + + SwView* pView; + std::unique_ptr mpViewOption; + const SwViewOption* mpConstViewOption; + bool bObjectValid:1, mbApplyZoom; + + FieldUnit eHRulerUnit; + bool mbApplyHRulerMetric; + FieldUnit 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() + throw() 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 bObjectValid;} + void Invalidate() {bObjectValid = false;} +}; + +#endif + +/* 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 000000000..4e72a5309 --- /dev/null +++ b/sw/source/uibase/inc/unotools.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_UNOTOOLS_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_UNOTOOLS_HXX + +#include +#include +#include +#include +#include +#include + +#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 SW_DLLPUBLIC SwOneExampleFrame : public weld::CustomWidgetController +{ + ScopedVclPtr m_xVirDev; + css::uno::Reference< css::frame::XModel > m_xModel; + css::uno::Reference< css::frame::XController > m_xController; + css::uno::Reference< css::text::XTextCursor > m_xCursor; + + Idle m_aLoadedIdle; + Link m_aInitializedLink; + + OUString m_sArgumentURL; + + SwView* m_pModuleView; + + sal_uInt32 m_nStyleFlags; + + bool m_bIsInitialized; + + DECL_DLLPRIVATE_LINK( TimeoutHdl, Timer*, void ); + void PopupHdl(const OString& rId); + + SAL_DLLPRIVATE void CreateControl(); + SAL_DLLPRIVATE void DisposeControl(); + +public: + SwOneExampleFrame(sal_uInt32 nStyleFlags, + const Link* pInitalizedLink, + 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;} + css::uno::Reference< css::text::XTextCursor > & 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 000000000..db2f6eae3 --- /dev/null +++ b/sw/source/uibase/inc/unotxvw.hxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class SdrObject; +class SwView; + +class SwXTextView : + public css::view::XSelectionSupplier, + public css::lang::XServiceInfo, + public css::view::XFormLayerAccess, + public css::text::XTextViewCursorSupplier, + public css::text::XRubySelection, + public css::view::XViewSettingsSupplier, + public css::beans::XPropertySet, + public css::datatransfer::XTransferableSupplier, + public SfxBaseController +{ + ::comphelper::OInterfaceContainerHelper2 m_SelChangedListeners; + + SwView* m_pView; + const SfxItemPropertySet* m_pPropSet; // property map for SwXTextView properties + // (not related to mxViewSettings!) + + css::uno::Reference< css::beans::XPropertySet > mxViewSettings; + css::uno::Reference< css::text::XTextViewCursor > mxTextViewCursor; + + SdrObject* GetControl( + const css::uno::Reference< css::awt::XControlModel > & Model, + css::uno::Reference< css::awt::XControl >& xToFill ); + +protected: + virtual ~SwXTextView() override; +public: + SwXTextView(SwView* pSwView); + + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire( ) throw() override; + virtual void SAL_CALL release( ) throw() override; + + //XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override; + + //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; + + //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; + + 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); + + DECLARE_XINTERFACE() + + //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; + + static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId(); + + //XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) 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 000000000..163654686 --- /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 +#include +#include +#include +#include + +class SwMasterUsrPref; + +class SwContentViewConfig : public utl::ConfigItem +{ +private: + SwMasterUsrPref& rParent; + bool bWeb; + + css::uno::Sequence 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 : public utl::ConfigItem +{ +private: + SwMasterUsrPref& rParent; + bool bWeb; + + css::uno::Sequence 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 : public utl::ConfigItem +{ +private: + SwMasterUsrPref& rParent; + + static css::uno::Sequence 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 : public utl::ConfigItem +{ +private: + SwMasterUsrPref& rParent; + + static css::uno::Sequence 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 : public utl::ConfigItem +{ +private: + SwMasterUsrPref& rParent; + css::uno::Sequence 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 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 000000000..b531ef4f2 --- /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 +#include + +class SwViewLayoutControl : public SfxStatusBarControl +{ +private: + + struct SwViewLayoutControl_Impl; + std::unique_ptr mpImpl; + +public: + + SFX_DECL_STATUSBAR_CONTROL(); + + SwViewLayoutControl( sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb ); + virtual ~SwViewLayoutControl() override; + + virtual void StateChanged( 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 000000000..dff87a792 --- /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 +#include +#include +#include + +class SwWatermarkDialog : 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 m_xTextInput; + std::unique_ptr m_xOKButton; + std::unique_ptr m_xFont; + std::unique_ptr m_xAngle; + std::unique_ptr m_xTransparency; + std::unique_ptr 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 000000000..dfce5359f --- /dev/null +++ b/sw/source/uibase/inc/wformsh.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_WFORMSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WFORMSH_HXX + +#include "drformsh.hxx" + +class SwWebDrawFormShell : public SwDrawFormShell +{ +public: + SwWebDrawFormShell(SwView &rShell); + virtual ~SwWebDrawFormShell() override; + + SFX_DECL_INTERFACE(SW_WEBDRAWFORMSHELL) + +private: + /// SfxInterface initializer. + static void InitInterface_Impl(); + +public: +}; + +#endif + +/* 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 000000000..15cd8a8b7 --- /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: 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 000000000..65987a423 --- /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: 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 000000000..f3a1179a6 --- /dev/null +++ b/sw/source/uibase/inc/wlistsh.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_WLISTSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WLISTSH_HXX + +#include "listsh.hxx" + +class SwWebListShell: public SwListShell +{ +public: + SFX_DECL_INTERFACE(SW_WEBLISTSHELL) + +private: + /// SfxInterface initializer. + static void InitInterface_Impl(); + +public: + + SwWebListShell(SwView &rView); + virtual ~SwWebListShell() override; +}; + +#endif + +/* 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 000000000..017768aac --- /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: 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 000000000..7b6f86204 --- /dev/null +++ b/sw/source/uibase/inc/wordcountctrl.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/. + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTCTRL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WORDCOUNTCTRL_HXX + +#include + +/** +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 : public SfxStatusBarControl +{ +public: + SFX_DECL_STATUSBAR_CONTROL(); + + SwWordCountStatusBarControl(sal_uInt16 nSlotId, sal_uInt16 nId, StatusBar& rStb); + virtual ~SwWordCountStatusBarControl() override; + + virtual void StateChanged( 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 000000000..dafc87ea0 --- /dev/null +++ b/sw/source/uibase/inc/wordcountdialog.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +struct SwDocStat; +#include +#include + +class SwWordCountFloatDlg : public SfxModelessDialogController +{ + void SetValues(const SwDocStat& rCurrent, const SwDocStat& rDoc); + void showCJK(bool bShowCJK); + void showStandardizedPages(bool bShowStandardizedPages); + + std::unique_ptr m_xCurrentWordFT; + std::unique_ptr m_xCurrentCharacterFT; + std::unique_ptr m_xCurrentCharacterExcludingSpacesFT; + std::unique_ptr m_xCurrentCjkcharsFT; + std::unique_ptr m_xCurrentStandardizedPagesFT; + std::unique_ptr m_xDocWordFT; + std::unique_ptr m_xDocCharacterFT; + std::unique_ptr m_xDocCharacterExcludingSpacesFT; + std::unique_ptr m_xDocCjkcharsFT; + std::unique_ptr m_xDocStandardizedPagesFT; + std::unique_ptr m_xCjkcharsLabelFT; + std::unique_ptr m_xCjkcharsLabelFT2; + std::unique_ptr m_xStandardizedPagesLabelFT; + std::unique_ptr m_xStandardizedPagesLabelFT2; + +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 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 000000000..20949f728 --- /dev/null +++ b/sw/source/uibase/inc/workctrl.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_WORKCTRL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WORKCTRL_HXX + +#include +#include + +class PopupMenu; +class SwView; + +// 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_COUNT 18 + +class SwTbxAutoTextCtrl : public SfxToolBoxControl +{ +public: + SFX_DECL_TOOLBOX_CONTROL(); + + SwTbxAutoTextCtrl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ); + virtual ~SwTbxAutoTextCtrl() override; + + virtual void CreatePopupWindow() override; + virtual void StateChanged( sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState ) override; + + DECL_STATIC_LINK(SwTbxAutoTextCtrl, PopupHdl, Menu*, bool); +}; + +class SwPreviewZoomControl : public SfxToolBoxControl +{ +public: + SFX_DECL_TOOLBOX_CONTROL(); + + SwPreviewZoomControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ); + virtual ~SwPreviewZoomControl() override; + + virtual void StateChanged( sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState ) override; + + virtual VclPtr CreateItemWindow( vcl::Window *pParent ) override; +}; + +class SwJumpToSpecificPageControl : public SfxToolBoxControl +{ +public: + SFX_DECL_TOOLBOX_CONTROL(); + + SwJumpToSpecificPageControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ); + virtual ~SwJumpToSpecificPageControl() override; + + virtual VclPtr CreateItemWindow( vcl::Window *pParent ) override; +}; +#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 000000000..60313ffd4 --- /dev/null +++ b/sw/source/uibase/inc/wrap.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_WRAP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WRAP_HXX + +#include +#include +#include + +namespace vcl { class Window; } +class SfxItemSet; +class SwWrtShell; + +class SwWrapDlg : public SfxSingleTabDialogController +{ +public: + SwWrapDlg(weld::Window* pParent, SfxItemSet& rSet, SwWrtShell* pSh, bool bDrawMode); +}; + +// circulation TabPage +class SwWrapTabPage: 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 m_xNoWrapRB; + std::unique_ptr m_xWrapLeftRB; + std::unique_ptr m_xWrapRightRB; + std::unique_ptr m_xWrapParallelRB; + std::unique_ptr m_xWrapThroughRB; + std::unique_ptr m_xIdealWrapRB; + + // MARGIN + std::unique_ptr m_xLeftMarginED; + std::unique_ptr m_xRightMarginED; + std::unique_ptr m_xTopMarginED; + std::unique_ptr m_xBottomMarginED; + + // OPTIONS + std::unique_ptr m_xWrapAnchorOnlyCB; + std::unique_ptr m_xWrapTransparentCB; + std::unique_ptr m_xWrapOutlineCB; + std::unique_ptr m_xWrapOutsideCB; + std::unique_ptr 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::ToggleButton&, void); + DECL_LINK(ContourHdl, weld::ToggleButton&, void); + + static const sal_uInt16 m_aWrapPageRg[]; + +public: + SwWrapTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); + static std::unique_ptr 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 const sal_uInt16* GetRanges() { return m_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; } +}; + +#endif + +/* 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 000000000..4c02e5e46 --- /dev/null +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -0,0 +1,652 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_WRTSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WRTSH_HXX + +#include +#include +#include +#include +#include "navmgr.hxx" +#include +#include +#include +#include + +namespace vcl { class Window; } +class SbxArray; +class SwDoc; +class SwViewOption; +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; + +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 : is_typed_flags {}; +} + +/** 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: 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 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 SwEditShell::Insert; + + 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); } + long KillSelection(const Point* pPt, bool bProp) { return (this->*m_fnKillSel)(pPt, bProp); } + + bool IsSplitVerticalByDefault() const; + void SetSplitVerticalByDefault(bool value); + + // reset all selections + 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 = SwCursorShell::PopMode::DeleteStack); + + void EnterStdMode(); + bool IsStdMode() const { return !m_bExtMode && !m_bAddMode && !m_bBlockMode; } + + void EnterExtMode(); + void LeaveExtMode(); + bool ToggleExtMode(); + bool IsExtMode() const { return m_bExtMode; } + + void EnterAddMode(); + void LeaveAddMode(); + void ToggleAddMode(); + bool IsAddMode() const { return m_bAddMode; } + + void EnterBlockMode(); + void LeaveBlockMode(); + bool 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 &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 ( sal_uInt16 nMode, bool bSelect, + sal_uInt16 nCount, bool bBasicCall, bool bVisual = false ); + bool Right ( sal_uInt16 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_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(); + 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 + void Insert(SwField const &, SwPaM* pAnnotationRange = nullptr); + void Insert(const OUString &); + // graphic + void Insert( 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& rPgNum = std::nullopt); + void InsertLineBreak(); + void InsertColumnBreak(); + 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( long nVerb = 0 ); // 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(const OUString &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 ); + OUString GetDoString( DoType eDoType ) const; + OUString GetRepeatString() const; + void GetDoStrings( DoType eDoType, SfxStringListItem& rStrLstItem ) const; + + // search and replace + sal_uLong SearchPattern(const i18nutil::SearchOptions2& rSearchOpt, + bool bSearchInNotes, + SwDocPositions eStart, SwDocPositions eEnd, + FindRanges eFlags = FindRanges::InBody, + bool bReplace = false ); + + sal_uLong SearchTempl (const OUString &rTempl, + SwDocPositions eStart, SwDocPositions eEnd, + FindRanges eFlags = FindRanges::InBody, + const OUString* pReplTempl = nullptr ); + + sal_uLong 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 ); + + // 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 ); + 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( const OUString& rName ); + bool GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType = 0, + sal_uInt16 nSeqNo = 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); + + void ChangeHeaderOrFooter(const OUString& 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); + +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 pNext; + bool bValidCurPos : 1; + bool bIsFrameSel : 1; + SwTwips lOffset; + + CursorStack( bool bValid, bool bFrameSel, const Point &rDocPos, + SwTwips lOff, std::unique_ptr pN ) + : aDocPos(rDocPos), + pNext(std::move(pN)), + bValidCurPos( bValid ), + bIsFrameSel( bFrameSel ), + lOffset(lOff) + { + } + + }; + std::unique_ptr 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 m_aSelTableLink; + + // resets the cursor stack after movement by PageUp/-Down + SAL_DLLPRIVATE void ResetCursorStack_(); + + using SwCursorShell::SetCursor; + SAL_DLLPRIVATE long SetCursor(const Point *, bool bProp=false ); + + SAL_DLLPRIVATE 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 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 &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 +} + +#endif + +/* 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 000000000..041175019 --- /dev/null +++ b/sw/source/uibase/inc/wtabsh.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_WTABSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WTABSH_HXX + +#include "tabsh.hxx" + +class SwWebTableShell: public SwTableShell +{ +public: + SFX_DECL_INTERFACE(SW_WEBTABSHELL) + +private: + /// SfxInterface initializer. + static void InitInterface_Impl(); + +public: + SwWebTableShell(SwView &rView); + virtual ~SwWebTableShell() override; +}; + +#endif + +/* 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 000000000..7924fdf90 --- /dev/null +++ b/sw/source/uibase/inc/wtextsh.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_WTEXTSH_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WTEXTSH_HXX + +#include "textsh.hxx" + +class SwWebTextShell: public SwTextShell +{ +public: + SFX_DECL_INTERFACE(SW_WEBTEXTSHELL) + +private: + /// SfxInterface initializer. + static void InitInterface_Impl(); + +public: + SwWebTextShell(SwView &rView); + virtual ~SwWebTextShell() override; +}; + +#endif + +/* 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 000000000..cfd63881d --- /dev/null +++ b/sw/source/uibase/inc/wview.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_WVIEW_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_WVIEW_HXX + +#include +#include + +class SW_DLLPUBLIC SwWebView: public SwView +{ +protected: + virtual void SelectShell() override; + +public: + SFX_DECL_VIEWFACTORY(SwWebView); + SFX_DECL_INTERFACE(SW_WEBVIEWSHELL) + +private: + /// SfxInterface initializer. + static void InitInterface_Impl(); + +public: + SwWebView(SfxViewFrame* pFrame, SfxViewShell*); + virtual ~SwWebView() override; +}; + +#endif + +/* 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 000000000..d0802989a --- /dev/null +++ b/sw/source/uibase/inc/zoomctrl.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_ZOOMCTRL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_INC_ZOOMCTRL_HXX + +#include + +class SwZoomControl : public SvxZoomStatusBarControl +{ +private: + OUString sPreviewZoom; +public: + virtual void Command( const CommandEvent& rCEvt ) override; + virtual void StateChanged( 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; + +}; + +#endif + +/* 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 000000000..a6deaa821 --- /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 +#include +#include + +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(); + xAbstDlg = pFact->CreateIndexMarkFloatDlg(pBindings, this, pParentWindow->GetFrameWeld(), pInfo); + SetController(xAbstDlg->GetController()); +} + +SfxChildWinInfo SwInsertIdxMarkWrapper::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); + + return aInfo; +} + +void SwInsertIdxMarkWrapper::ReInitDlg(SwWrtShell& rWrtShell) +{ + 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(); + xAbstDlg = pFact->CreateAuthMarkFloatDlg(pBindings, this, pParentWindow->GetFrameWeld(), pInfo); + SetController(xAbstDlg->GetController()); +} + +SfxChildWinInfo SwInsertAuthMarkWrapper::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); + return aInfo; +} + +void SwInsertAuthMarkWrapper::ReInitDlg(SwWrtShell& rWrtShell) +{ + 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 000000000..4e7e65f9c --- /dev/null +++ b/sw/source/uibase/index/toxmgr.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 +#include +#include +#include +#include +#include +#include + +// handle indexes with TOXMgr +SwTOXMgr::SwTOXMgr(SwWrtShell* pShell): + pSh(pShell) +{ + pSh->GetCurTOXMarks(aCurMarks); + SetCurTOXMark(0); +} + +SwTOXMark* SwTOXMgr::GetTOXMark(sal_uInt16 nId) +{ + if(!aCurMarks.empty()) + return aCurMarks[nId]; + return nullptr; +} + +void SwTOXMgr::DeleteTOXMark() +{ + SwTOXMark* pNext = nullptr; + if( pCurTOXMark ) + { + pNext = const_cast(&pSh->GotoTOXMark( *pCurTOXMark, TOX_NXT )); + if( pNext == pCurTOXMark ) + pNext = nullptr; + + pSh->DeleteTOXMark( pCurTOXMark ); + pSh->SetModified(); + } + // go to next one + 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(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(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(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(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; + + pSh->StartAllAction(); + pSh->SwEditShell::Insert(*pMark); + pSh->EndAllAction(); +} + +// Update of TOXMarks +void SwTOXMgr::UpdateTOXMark(const SwTOXMarkDescription& rDesc) +{ + assert(pCurTOXMark && "no current TOXMark"); + pSh->StartAllAction(); + if(pCurTOXMark->GetTOXType()->GetType() == TOX_INDEX) + { + if(rDesc.GetPrimKey() && !rDesc.GetPrimKey()->isEmpty() ) + { + pCurTOXMark->SetPrimaryKey( *rDesc.GetPrimKey() ); + if(rDesc.GetPhoneticReadingOfPrimKey()) + pCurTOXMark->SetPrimaryKeyReading( *rDesc.GetPhoneticReadingOfPrimKey() ); + else + pCurTOXMark->SetPrimaryKeyReading(OUString()); + + if( rDesc.GetSecKey() && !rDesc.GetSecKey()->isEmpty() ) + { + pCurTOXMark->SetSecondaryKey( *rDesc.GetSecKey() ); + if(rDesc.GetPhoneticReadingOfSecKey()) + pCurTOXMark->SetSecondaryKeyReading( *rDesc.GetPhoneticReadingOfSecKey() ); + else + pCurTOXMark->SetSecondaryKeyReading(OUString()); + } + else + { + pCurTOXMark->SetSecondaryKey(OUString()); + pCurTOXMark->SetSecondaryKeyReading(OUString()); + } + } + else + { + pCurTOXMark->SetPrimaryKey(OUString()); + pCurTOXMark->SetPrimaryKeyReading(OUString()); + pCurTOXMark->SetSecondaryKey(OUString()); + pCurTOXMark->SetSecondaryKeyReading(OUString()); + } + if(rDesc.GetPhoneticReadingOfAltStr()) + pCurTOXMark->SetTextReading( *rDesc.GetPhoneticReadingOfAltStr() ); + else + pCurTOXMark->SetTextReading(OUString()); + pCurTOXMark->SetMainEntry(rDesc.IsMainEntry()); + } + else + 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 = pCurTOXMark->IsAlternativeText(); + if( bReplace ) + pCurTOXMark->SetAlternativeText( *rDesc.GetAltStr() ); + else + { + SwTOXMark aCpy( *pCurTOXMark ); + aCurMarks.clear(); + pSh->DeleteTOXMark(pCurTOXMark); + aCpy.SetAlternativeText( *rDesc.GetAltStr() ); + pSh->SwEditShell::Insert( aCpy ); + pCurTOXMark = nullptr; + } + } + pSh->SetModified(); + pSh->EndAllAction(); + // Bug 36207 pCurTOXMark points nowhere here! + if(!pCurTOXMark) + { + pSh->Left(CRSR_SKIP_CHARS, false, 1, false ); + pSh->GetCurTOXMarks(aCurMarks); + SetCurTOXMark(0); + } +} + +// determine UserTypeID +sal_uInt16 SwTOXMgr::GetUserTypeID(const OUString& rStr) +{ + sal_uInt16 nSize = pSh->GetTOXTypeCount(TOX_USER); + for(sal_uInt16 i=0; i < nSize; ++i) + { + const SwTOXType* pTmp = pSh->GetTOXType(TOX_USER, i); + if(pTmp && pTmp->GetTypeName() == rStr) + return i; + } + SwTOXType aUserType(*pSh->GetDoc(), TOX_USER, rStr); + pSh->InsertTOXType(aUserType); + return nSize; +} + +// traveling between TOXMarks +void SwTOXMgr::NextTOXMark(bool bSame) +{ + OSL_ENSURE(pCurTOXMark, "no current TOXMark"); + if( pCurTOXMark ) + { + SwTOXSearch eDir = bSame ? TOX_SAME_NXT : TOX_NXT; + pCurTOXMark = const_cast(&pSh->GotoTOXMark( *pCurTOXMark, eDir )); + } +} + +void SwTOXMgr::PrevTOXMark(bool bSame) +{ + OSL_ENSURE(pCurTOXMark, "no current TOXMark"); + if( pCurTOXMark ) + { + SwTOXSearch eDir = bSame ? TOX_SAME_PRV : TOX_PRV; + pCurTOXMark = const_cast(&pSh->GotoTOXMark(*pCurTOXMark, eDir )); + } +} + +const SwTOXType* SwTOXMgr::GetTOXType(TOXTypes eTyp) const +{ + return pSh->GetTOXType(eTyp, 0); +} + +void SwTOXMgr::SetCurTOXMark(sal_uInt16 nId) +{ + pCurTOXMark = (nId < aCurMarks.size()) ? aCurMarks[nId] : nullptr; +} + +bool SwTOXMgr::UpdateOrInsertTOX(const SwTOXDescription& rDesc, + SwTOXBase** ppBase, + const SfxItemSet* pSet) +{ + SwWait aWait( *pSh->GetView().GetDocShell(), true ); + bool bRet = true; + const SwTOXBase* pCurTOX = ppBase && *ppBase ? *ppBase : pSh->GetCurTOX(); + SwTOXBase* pTOX = const_cast(pCurTOX); + + SwTOXBase * pNewTOX = nullptr; + + if (pTOX) + pNewTOX = new SwTOXBase(*pTOX); + + TOXTypes eCurTOXType = rDesc.GetTOXType(); + if(pCurTOX && !ppBase && pSh->HasSelection()) + pSh->EnterStdMode(); + + switch(eCurTOXType) + { + case TOX_INDEX : + { + if(!pCurTOX || (ppBase && !(*ppBase))) + { + const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, 0); + SwForm aForm(eCurTOXType); + pNewTOX = new SwTOXBase(pType, aForm, SwTOXElement::Mark, pType->GetTypeName()); + } + pNewTOX->SetOptions(rDesc.GetIndexOptions()); + pNewTOX->SetMainEntryCharStyle(rDesc.GetMainEntryCharStyle()); + pSh->SetTOIAutoMarkURL(rDesc.GetAutoMarkURL()); + pSh->ApplyAutoMark(); + } + break; + case TOX_CONTENT : + { + if(!pCurTOX || (ppBase && !(*ppBase))) + { + const SwTOXType* pType = 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 = pSh->GetTOXTypeCount(eCurTOXType); + for(sal_uInt16 i=0; rDesc.GetTOUName() && i < nSize; ++i) + { const SwTOXType* pType = pSh->GetTOXType(TOX_USER, i); + if(pType->GetTypeName() == *rDesc.GetTOUName()) + { nPos = i; + break; + } + } + const SwTOXType* pType = pSh->GetTOXType(eCurTOXType, nPos); + + SwForm aForm(eCurTOXType); + pNewTOX = new SwTOXBase(pType, aForm, rDesc.GetContentOptions(), pType->GetTypeName()); + + } + else + { + const_cast( pCurTOX )->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( + pSh->GetFieldType(SwFieldIds::TableOfAuthorities, OUString())); + if (!pFType) + { + SwAuthorityFieldType const type(pSh->GetDoc()); + pFType = static_cast( + 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 = pSh->GetTOXType(eCurTOXType, 0); + SwForm aForm(eCurTOXType); + pNewTOX = new SwTOXBase( + pType, aForm, + TOX_AUTHORITIES == eCurTOXType ? SwTOXElement::Mark : SwTOXElement::NONE, + pType->GetTypeName()); + } + else + { + if((!ppBase || !(*ppBase)) && pSh->HasSelection()) + pSh->DelRight(); + pNewTOX = const_cast(pCurTOX); + } + pNewTOX->SetFromObjectNames(rDesc.IsCreateFromObjectNames()); + pNewTOX->SetOLEOptions(rDesc.GetOLEOptions()); + } + 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 + { + pSh->InsertTableOf(*pNewTOX, pSet); + delete pNewTOX; + } + } + else + { + SwDoc * pDoc = pSh->GetDoc(); + + if (pDoc->GetIDocumentUndoRedo().DoesUndo()) + { + pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::TOXCHANGE, nullptr); + } + + pDoc->ChangeTOX(*pTOX, *pNewTOX); + + pTOX->DisableKeepExpression(); + 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 000000000..168f6246a --- /dev/null +++ b/sw/source/uibase/lingu/hhcwrp.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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "sdrhhcwrap.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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_pWin( &pSwView->GetEditWin() ) + , 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() +{ + 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 )) + { + 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()->nContent.GetIndex(); +} + +void SwHHCWrapper::SelectNewUnit_impl( sal_Int32 nUnitStart, sal_Int32 nUnitEnd ) +{ + SwPaM *pCursor = m_rWrtShell.GetCursor(); + pCursor->GetPoint()->nContent = m_nLastPos; + pCursor->DeleteMark(); + + m_rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ false, + static_cast(m_nUnitOffset + nUnitStart), true ); + pCursor->SetMark(); + m_rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ true, + static_cast(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, + const OUString& rOrigText, + 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->nContent.GetIndex(); + const SwNodeIndex aStartNodeIndex = pStart->nNode; + SwTextNode *pStartTextNode = aStartNodeIndex.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! + 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 = rOrigText.getLength(); + } + + if (nPos == nConvTextLen || /* end of string also terminates non-matching char sequence */ + rOrigText[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()->nContent.Assign( pStartTextNode, nChgInNodeStartIndex ); + m_rWrtShell.GetCursor()->GetPoint()->nContent.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()->nContent.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 + sal_uInt16 const aRanges[] { + RES_CHRATR_BEGIN, RES_FRMATR_END, + 0, 0, 0 }; + SfxItemSet aItemSet( m_rWrtShell.GetAttrPool(), aRanges ); + // get all attributes spanning the whole selection in order to + // restore those for the new text + m_rWrtShell.GetCurAttr( aItemSet ); + + m_rWrtShell.Delete(); + 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->nContent = pMark->nContent.GetIndex() - 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(); + 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 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( 0, true, aNewOrigText.getLength(), true, true ); + } + + pRuby->SetPosition( static_cast(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()->nContent -= aNewText.getLength(); + + OSL_ENSURE( GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED || GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL, + "SwHHCWrapper::ReplaceUnit : unexpected target language" ); + + sal_uInt16 const aRanges[] { + RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT, + 0, 0, 0 }; + + SfxItemSet aSet( m_rWrtShell.GetAttrPool(), aRanges ); + 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(); + SwPosition* pSttPos = pCursor->Start(); + SwPosition* pEndPos = pCursor->End(); + + if (pSttPos->nNode.GetNode().IsTextNode() && + pEndPos->nNode.GetNode().IsTextNode()) + { + m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), + pSttPos->nNode.GetNode().GetTextNode(), pSttPos->nContent, + pEndPos->nNode.GetNode().GetTextNode(), pEndPos->nContent ) ); + } + 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->nNode.GetNode().GetTextNode(); + // just in case we check anyway... + if (!pTextNode || !pTextNode->IsTextNode()) + return; + m_pConvArgs.reset( new SwConversionArgs( GetSourceLanguage(), + pTextNode, pSttPos->nContent, + pTextNode, pSttPos->nContent ) ); + } + OSL_ENSURE( m_pConvArgs->pStartNode && m_pConvArgs->pStartNode->IsTextNode(), + "failed to get proper start text node" ); + OSL_ENSURE( m_pConvArgs->pEndNode && m_pConvArgs->pEndNode->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->pStartNode->GetText() ); + const sal_Int32 nPos = m_pConvArgs->pStartIdx->GetIndex(); + 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->pStartIdx = 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; + + m_pWin->EnterWait(); + bool bConv = true; + + while ( bConv ) + { + bFound = ConvContinue_impl( m_pConvArgs.get() ); + if (bFound) + { + bConv = false; + } + else + { + ConvEnd_impl( m_pConvArgs.get() ); + bConv = ConvNext_impl(); + } + } + m_pWin->LeaveWait(); +} + +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 000000000..d7d0c87a5 --- /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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define PSH (&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 ), + pView( pVw ), + nPageCount( 0 ), + nPageStart( 0 ), + bInSelection( bSelect ), + bInfoBox( false ) +{ + uno::Reference< linguistic2::XLinguProperties > xProp( GetLinguPropertySet() ); + bAutomatic = xProp.is() && xProp->getIsHyphAuto(); +} + +void SwHyphWrapper::SpellStart( SvxSpellArea eSpell ) +{ + if( SvxSpellArea::Other == eSpell && nPageCount ) + { + ::EndProgress( pView->GetDocShell() ); + nPageCount = 0; + nPageStart = 0; + } + pView->HyphStart( eSpell ); +} + +void SwHyphWrapper::SpellContinue() +{ + // for automatic separation, make actions visible only at the end + std::unique_ptr pWait; + if( bAutomatic ) + { + PSH->StartAllAction(); + pWait.reset(new SwWait( *pView->GetDocShell(), true )); + } + + uno::Reference< uno::XInterface > xHyphWord = bInSelection ? + PSH->HyphContinue( nullptr, nullptr ) : + PSH->HyphContinue( &nPageCount, &nPageStart ); + SetLast( xHyphWord ); + + // for automatic separation, make actions visible only at the end + if( bAutomatic ) + { + PSH->EndAllAction(); + pWait.reset(); + } +} + +void SwHyphWrapper::SpellEnd() +{ + PSH->HyphEnd(); + SvxSpellWrapper::SpellEnd(); +} + +bool SwHyphWrapper::SpellMore() +{ + PSH->Push(); + 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( nPageCount ) + ::EndProgress( pView->GetDocShell() ); + if( bInfoBox && !Application::IsHeadlessModeEnabled() ) + { + std::unique_ptr xInfoBox(Application::CreateMessageDialog(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 000000000..27d4b19ff --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(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(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, + const uno::Reference< linguistic2::XSpellAlternatives > &xAlt, + const OUString &rParaText) + : m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/spellmenu.ui", "") + , m_xPopupMenu(m_aBuilder.get_menu("menu")) + , m_nIgnoreWordId(m_xPopupMenu->GetItemId("ignoreall")) + , m_nAddMenuId(m_xPopupMenu->GetItemId("addmenu")) + , m_nAddId(m_xPopupMenu->GetItemId("add")) + , m_nSpellDialogId(m_xPopupMenu->GetItemId("spelldialog")) + , m_nCorrectMenuId(m_xPopupMenu->GetItemId("correctmenu")) + , m_nCorrectDialogId(m_xPopupMenu->GetItemId("correctdialog")) + , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId("langselection")) + , m_nLangParaMenuId(m_xPopupMenu->GetItemId("langpara")) + , m_nRedlineAcceptId(m_xPopupMenu->GetItemId("accept")) + , m_nRedlineRejectId(m_xPopupMenu->GetItemId("reject")) + , m_nRedlineNextId(m_xPopupMenu->GetItemId("next")) + , m_nRedlinePrevId(m_xPopupMenu->GetItemId("prev")) + , m_pSh( pWrtSh ) + , m_xSpellAlt(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(OString(), 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, OString(), 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, OString(), 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(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( 4 ); + aSeq[0] = aCurrentLang; + aSeq[1] = aScriptTypesInUse; + aSeq[2] = aKeyboardLang; + aSeq[3] = 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, 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, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/spellmenu.ui", "") + , m_xPopupMenu(m_aBuilder.get_menu("menu")) + , m_nIgnoreWordId(m_xPopupMenu->GetItemId("ignoreall")) + , m_nAddMenuId(m_xPopupMenu->GetItemId("addmenu")) + , m_nAddId(m_xPopupMenu->GetItemId("add")) + , m_nSpellDialogId(m_xPopupMenu->GetItemId("spelldialog")) + , m_nCorrectMenuId(m_xPopupMenu->GetItemId("correctmenu")) + , m_nCorrectDialogId(m_xPopupMenu->GetItemId("correctdialog")) + , m_nLangSelectionMenuId(m_xPopupMenu->GetItemId("langselection")) + , m_nLangParaMenuId(m_xPopupMenu->GetItemId("langpara")) + , m_nRedlineAcceptId(m_xPopupMenu->GetItemId("accept")) + , m_nRedlineRejectId(m_xPopupMenu->GetItemId("reject")) + , m_nRedlineNextId(m_xPopupMenu->GetItemId("next")) + , m_nRedlinePrevId(m_xPopupMenu->GetItemId("prev")) + , m_pSh(pWrtSh) + , m_sExplanationLink() + , 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(OString(), nPos++); + m_xPopupMenu->InsertItem(MN_SHORT_COMMENT, aMessageText, MenuItemBits::NOSELECT, OString(), 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, OString(), nPos++); + } + + m_xPopupMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); + + m_xPopupMenu->InsertSeparator(OString(), 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, OString(), nPos++); + m_xPopupMenu->SetHelpId(nItemId, HID_LINGU_REPLACE); + if (!aSuggestionImageUrl.isEmpty()) + m_xPopupMenu->SetItemImage(nItemId, aImage); + + ++nItemId; + } + m_xPopupMenu->InsertSeparator(OString(), 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, OString(), 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(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( 4 ); + aSeq[0] = aCurrentLang; + aSeq[1] = aScriptTypesInUse; + aSeq[2] = aKeyboardLang; + aSeq[3] = 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, true); + + SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, uno::makeAny( true )); + + InitItemCommands(rSuggestions); +} + +SwSpellPopup::~SwSpellPopup() {} + +void SwSpellPopup::InitItemCommands(const css::uno::Sequence< OUString >& aSuggestions) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + // 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(); + SfxItemSet aSet(pDoc->GetAttrPool(), svl::Items{}); + 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(CRSR_SKIP_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 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 000000000..d21ffaa24 --- /dev/null +++ b/sw/source/uibase/lingu/sdrhhcwrap.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include "sdrhhcwrap.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +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 ), + pView( pVw ), + pTextObj( nullptr ), + nOptions( nConvOptions ), + nDocIndex( 0 ), + nSourceLang( nSourceLanguage ), + nTargetLang( nTargetLanguage ), + pTargetFont( pTargetFnt ), + bIsInteractive( bInteractive ) +{ + SetRefDevice( pView->GetDocShell()->GetDoc()->getIDocumentDeviceAccess().getPrinter( false ) ); + + MapMode aMapMode (MapUnit::MapTwip); + SetRefMapMode(aMapMode); + + Size aSize( 1, 1 ); + SetPaperSize( aSize ); + + pOutlView.reset( new OutlinerView( this, &(pView->GetEditWin()) ) ); + pOutlView->GetOutliner()->SetRefDevice(pView->GetWrtShell().getIDocumentDeviceAccess().getPrinter( false )); + + // Hack: all SdrTextObj attributes should be transferred to EditEngine + pOutlView->SetBackgroundColor( COL_WHITE ); + + InsertView( pOutlView.get() ); + Point aPoint( 0, 0 ); + tools::Rectangle aRect( aPoint, aSize ); + pOutlView->SetOutputArea( aRect ); +// SetText( NULL ); + ClearModifyFlag(); +} + +SdrHHCWrapper::~SdrHHCWrapper() +{ + if (pTextObj) + { + SdrView *pSdrView = pView->GetWrtShell().GetDrawView(); + OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" ); + pSdrView->SdrEndTextEdit( true ); + SetUpdateMode(false); + pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1, 1) ) ); + } + RemoveView( pOutlView.get() ); + pOutlView.reset(); +} + +void SdrHHCWrapper::StartTextConversion() +{ + pOutlView->StartTextConversion( nSourceLang, nTargetLang, pTargetFont, nOptions, bIsInteractive, true ); +} + +bool SdrHHCWrapper::ConvertNextDocument() +{ + bool bNextDoc = false; + + if ( pTextObj ) + { + SdrView *pSdrView = pView->GetWrtShell().GetDrawView(); + OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" ); + pSdrView->SdrEndTextEdit( true ); + SetUpdateMode(false); + pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1, 1) ) ); + SetPaperSize( Size(1, 1) ); + Clear(); + pTextObj = nullptr; + } + + const auto n = nDocIndex; + + std::list aTextObjs; + SwDrawContact::GetTextObjectsFromFormat( aTextObjs, pView->GetDocShell()->GetDoc() ); + for (auto const& textObj : aTextObjs) + { + 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. + SetUpdateMode(true); + if (HasConvertibleTextPortion( nSourceLang )) + { + SdrView *pSdrView = pView->GetWrtShell().GetDrawView(); + OSL_ENSURE( pSdrView, "SdrHHCWrapper without DrawView?" ); + SdrPageView* pPV = pSdrView->GetSdrPageView(); + nDocIndex = n; + bNextDoc = true; + pOutlView->SetOutputArea( tools::Rectangle( Point(), Size(1,1))); + SetPaperSize( pTextObj->GetLogicRect().GetSize() ); + SetUpdateMode(true); + pView->GetWrtShell().MakeVisible(pTextObj->GetLogicRect()); + + pSdrView->SdrBeginTextEdit(pTextObj, pPV, &pView->GetEditWin(), false, this, pOutlView.get(), true, true); + } + else + SetUpdateMode(false); + } + + if ( !bNextDoc ) + 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 000000000..133e47cc9 --- /dev/null +++ b/sw/source/uibase/lingu/sdrhhcwrap.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_LINGU_SDRHHCWRAP_HXX +#define INCLUDED_SW_SOURCE_UIBASE_LINGU_SDRHHCWRAP_HXX + +#include + +class SwView; +class SdrTextObj; +class OutlinerView; + +class SdrHHCWrapper : public SdrOutliner +{ + // modified version of SdrSpeller + + SwView* pView; + SdrTextObj* pTextObj; + std::unique_ptr pOutlView; + sal_Int32 nOptions; + sal_uInt16 nDocIndex; + LanguageType nSourceLang; + LanguageType nTargetLang; + const vcl::Font* pTargetFont; + bool 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(); +}; + +#endif + +/* 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 000000000..868158732 --- /dev/null +++ b/sw/source/uibase/misc/glosdoc.cxx @@ -0,0 +1,627 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace +{ + +OUString lcl_FullPathName(const OUString& sPath, const OUString& sName) +{ + return sPath + "/" + sName + SwGlossaries::GetExtension(); +} + +OUString lcl_CheckFileName( const OUString& rNewFilePath, + const OUString& rNewGroupName ) +{ + const sal_Int32 nLen = rNewGroupName.getLength(); + 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 = rNewGroupName[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; + } + + OUString rSG = SwGlossaries::GetExtension(); + //generate generic name + utl::TempFile aTemp("group", true, &rSG, &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==sTemp.getToken(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 = sTemp.getToken(1, GLOS_DELIM).toUInt32(); + + 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 pGroup = GetGroupDoc(sGroup); + if(pGroup) + { + sRet = pGroup->GetName(); + } + return sRet; +} + +// supplies the group rName's text block document +std::unique_ptr 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 OUString sNewPath(rGroupName.getToken(1, GLOS_DELIM)); + sal_uInt16 nNewPath = static_cast(sNewPath.toInt32()); + if (static_cast(nNewPath) >= m_PathArr.size()) + return false; + const OUString sNewFilePath(m_PathArr[nNewPath]); + const OUString sNewGroup = lcl_CheckFileName(sNewFilePath, rGroupName.getToken(0, GLOS_DELIM)) + + OUStringChar(GLOS_DELIM) + sNewPath; + std::unique_ptr 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 = static_cast(rOldGroup.getToken(1, GLOS_DELIM).toInt32()); + if (static_cast(nOldPath) >= m_PathArr.size()) + return false; + + const OUString sOldFileURL = + lcl_FullPathName(m_PathArr[nOldPath], rOldGroup.getToken(0, GLOS_DELIM)); + + if (!FStatHelper::IsDocument( sOldFileURL )) + { + OSL_FAIL("group doesn't exist!"); + return false; + } + + sal_uInt16 nNewPath = static_cast(rNewGroup.getToken(1, GLOS_DELIM).toInt32()); + if (static_cast(nNewPath) >= m_PathArr.size()) + return false; + + const OUString sNewFileName = lcl_CheckFileName(m_PathArr[nNewPath], + rNewGroup.getToken(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); + } + + std::unique_ptr pNewBlock(new SwTextBlocks( sNewFileURL )); + pNewBlock->SetName(rNewTitle); + + return true; +} + +// Deletes a text block group +bool SwGlossaries::DelGroupDoc(const OUString &rName) +{ + sal_uInt16 nPath = static_cast(rName.getToken(1, GLOS_DELIM).toInt32()); + if (static_cast(nPath) >= m_PathArr.size()) + return false; + const OUString sBaseName(rName.getToken(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 SwGlossaries::GetGlosDoc( const OUString &rName, bool bCreate ) const +{ + sal_uInt16 nPath = static_cast(rName.getToken(1, GLOS_DELIM).toInt32()); + std::unique_ptr pTmp; + if (static_cast(nPath) < m_PathArr.size()) + { + const OUString sFileURL = + lcl_FullPathName(m_PathArr[nPath], rName.getToken(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 & SwGlossaries::GetNameList() +{ + if (m_GlosArr.empty()) + { + const OUString sExt( SwGlossaries::GetExtension() ); + for (size_t i = 0; i < m_PathArr.size(); ++i) + { + std::vector aFiles; + + SWUnoHelper::UCB_GetFileListOfFolder(m_PathArr[i], aFiles, &sExt); + for (const OUString& aTitle : aFiles) + { + const OUString sName( aTitle.copy( 0, aTitle.getLength() - sExt.getLength() ) + + OUStringChar(GLOS_DELIM) + OUString::number( static_cast(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& rPaths) +{ + std::vector::const_iterator aIt(rPaths.begin()); + const std::vector::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.getStr(); +} + +void SwGlossaries::UpdateGlosPath(bool bFull) +{ + SvtPathOptions aPathOpt; + const OUString& aNewPath( aPathOpt.GetAutoTextPath() ); + bool bPathChanged = m_aPath != aNewPath; + if (bFull || bPathChanged) + { + m_aPath = aNewPath; + + m_PathArr.clear(); + + std::vector aDirArr; + std::vector 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( *new StringErrorInfo( + 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() +{ + ErrCode nPathError = *new StringErrorInfo(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()) + { + auto it = std::find(m_GlosArr.begin(), m_GlosArr.end(), rGroup); + if (it != m_GlosArr.end()) + { + { + // tell the UNO AutoTextGroup object that it's not valid anymore + for ( UnoAutoTextGroups::iterator aLoop = m_aGlossaryGroups.begin(); + aLoop != m_aGlossaryGroups.end(); + ) + { + Reference< container::XNamed > xNamed( aLoop->get(), UNO_QUERY ); + if ( !xNamed.is() ) + { + aLoop = m_aGlossaryGroups.erase(aLoop); + } + else if ( xNamed->getName() == rGroup ) + { + static_cast< SwXAutoTextGroup* >( xNamed.get() )->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(); + ) + { + auto pEntry = comphelper::getUnoTunnelImplementation(aLoop->get()); + if ( pEntry && ( pEntry->GetGroupName() == rGroup ) ) + { + pEntry->Invalidate(); + aLoop = m_aGlossaryEntries.erase( aLoop ); + } + else + ++aLoop; + } + } + + m_GlosArr.erase(it); + } + } +} + +OUString SwGlossaries::GetCompleteGroupName( const OUString& rGroupName ) +{ + const size_t nCount = GetGroupCnt(); + // when the group name was created internally the path is here as well + sal_Int32 nIndex = 0; + const OUString sGroupName(rGroupName.getToken(0, GLOS_DELIM, nIndex)); + const bool bPathLen = !rGroupName.getToken(0, GLOS_DELIM, nIndex).isEmpty(); + for ( size_t i = 0; i < nCount; i++ ) + { + const OUString sGrpName = GetGroupName(i); + if (bPathLen) + { + if (rGroupName == sGrpName) + return sGrpName; + } + else + { + if (sGroupName == sGrpName.getToken(0, GLOS_DELIM)) + return sGrpName; + } + } + return OUString(); +} + +void SwGlossaries::InvalidateUNOOjects() +{ + // invalidate all the AutoTextGroup-objects + for (const auto& rGroup : m_aGlossaryGroups) + { + Reference< text::XAutoTextGroup > xGroup( rGroup.get(), UNO_QUERY ); + if ( xGroup.is() ) + static_cast< SwXAutoTextGroup* >( xGroup.get() )->Invalidate(); + } + UnoAutoTextGroups aTmpg; + m_aGlossaryGroups.swap( aTmpg ); + + // invalidate all the AutoTextEntry-objects + for (const auto& rEntry : m_aGlossaryEntries) + { + auto pEntry = comphelper::getUnoTunnelImplementation(rEntry.get()); + if ( pEntry ) + pEntry->Invalidate(); + } + UnoAutoTextEntries aTmpe; + m_aGlossaryEntries.swap( aTmpe ); +} + +Reference< text::XAutoTextGroup > SwGlossaries::GetAutoTextGroup( const OUString& _rGroupName ) +{ + bool _bCreate = true; + // first, find the name with path-extension + const OUString sCompleteGroupName = GetCompleteGroupName( _rGroupName ); + + Reference< text::XAutoTextGroup > xGroup; + + // look up the group in the cache + UnoAutoTextGroups::iterator aSearch = m_aGlossaryGroups.begin(); + for ( ; aSearch != m_aGlossaryGroups.end(); ) + { + auto pSwGroup = comphelper::getUnoTunnelImplementation(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(); + + Reference< text::XAutoTextEntry > xReturn; + + UnoAutoTextEntries::iterator aSearch( m_aGlossaryEntries.begin() ); + for ( ; aSearch != m_aGlossaryEntries.end(); ) + { + Reference< lang::XUnoTunnel > xEntryTunnel( aSearch->get(), UNO_QUERY ); + + SwXAutoTextEntry* pEntry = nullptr; + if ( xEntryTunnel.is() ) + pEntry = reinterpret_cast< SwXAutoTextEntry* >( xEntryTunnel->getSomething( SwXAutoTextEntry::getUnoTunnelId() ) ); + else + { + // 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 000000000..1e3c664f1 --- /dev/null +++ b/sw/source/uibase/misc/glshell.cxx @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ShellClass_SwWebGlosDocShell +#define ShellClass_SwGlosDocShell + +#include +#include +#include +#include + +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 ) + { + if( !rSh.HasName() ) + { + rReq.SetReturnValue( SfxBoolItem( 0, rSh.Save() ) ); + } + else + { + const SfxBoolItem* pRes = static_cast< const SfxBoolItem* >( + rSh.ExecuteSlot( rReq, + rSh.SfxObjectShell::GetInterface() )); + 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 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(), aGroupName, aShortName, aLongName ); + else + { + SetModified( false ); + return false; + } +} + +SwWebGlosDocShell::SwWebGlosDocShell() + : SwWebDocShell() +{ +} + +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(), aGroupName, aShortName, aLongName ); + else + { + SetModified( false ); + return false; + } +} + +SwDocShellRef SwGlossaries::EditGroupDoc( const OUString& rGroup, const OUString& rShortName, bool bShow ) +{ + SwDocShellRef xDocSh; + + std::unique_ptr 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( + xDocSh->GetDoc()->GetAttrPool(), + svl::Items< + SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, + SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, + FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>{}); + VclPtr pPrinter = VclPtr::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 000000000..d484cce5d --- /dev/null +++ b/sw/source/uibase/misc/numberingtypelistbox.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +struct SwNumberingTypeListBox_Impl +{ + uno::Reference xInfo; +}; + +SwNumberingTypeListBox::SwNumberingTypeListBox(std::unique_ptr pWidget) + : m_xWidget(std::move(pWidget)) + , m_xImpl(new SwNumberingTypeListBox_Impl) +{ + uno::Reference xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference 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 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(aTypes.begin(), aTypes.end(), nValue) != aTypes.end(); + } + } + if (bInsert) + { + OUString sId(OUString::number(nValue)); + m_xWidget->insert(nPos, SvxNumberingTypeTable::GetString(i), &sId, nullptr, nullptr); + } + } + if (nTypeFlags & SwInsertNumTypes::Extended) + { + for (sal_Int16 nCurrent : 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(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 000000000..a18506497 --- /dev/null +++ b/sw/source/uibase/misc/redlndlg.cxx @@ -0,0 +1,1261 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// -> #111827# +#include +#include +// <- #111827# + +#include +#include +#include + +#include + +#include +#include + +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(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(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_xDialog->weld_content_area()) + , 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 (pChildWin->GetOldDocShell() != pDocSh) + { // doc-switch + SwWait aWait( *pDocSh, false ); + SwWrtShell* pSh = pView->GetWrtShellPtr(); + + 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(const std::shared_ptr& rParent, weld::Builder *pBuilder, + weld::Container *pContentArea, bool bAutoFormat) + : m_xParentDlg(rParent) + , 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_xTabPagesCTRL(new SvxAcceptChgCtr(pContentArea, m_xParentDlg.get(), pBuilder)) + , m_xPopup(pBuilder->weld_menu("writermenu")) +{ + m_xTabPagesCTRL->set_help_id(HID_REDLINE_CTRL); + 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->EnableAcceptAll(false); + m_pTPView->EnableRejectAll(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) +{ + SwWait aWait( *::GetActiveView()->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_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 xSelEntry(rTreeView.make_iterator()); + if (rTreeView.get_selected(xSelEntry.get())) + rTreeView.scroll_to_row(*xSelEntry); //#i70937#, force the scroll +} + +void SwRedlineAcceptDlg::InitAuthors() +{ + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + + if (!m_xTabPagesCTRL) + return; + + SvxTPFilter *pFilterPage = m_xTabPagesCTRL->GetFilterPage(); + + std::vector aStrings; + OUString sOldAuthor(pFilterPage->GetSelectedAuthor()); + pFilterPage->ClearAuthors(); + + SwRedlineTable::size_type nCount = pSh->GetRedlineCount(); + + 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 bEnable = 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) +{ + switch (rRedln.GetType(nStack)) + { + case RedlineType::Insert: return BMP_REDLINE_INSERTED; + case RedlineType::Delete: return 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->EnableAcceptAll(false); + m_pTPView->EnableRejectAll(false); + return; // had the focus previously + } + + SwWait aWait( *pView->GetDocShell(), false ); + + m_aUsedSeqNo.clear(); + + // did something change? + SwWrtShell* pSh = pView->GetWrtShellPtr(); + 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 + if ((i = CalcDiff(i, false)) == SwRedlineTable::npos) + return; + continue; + } + + const SwRedlineData *pRedlineData = rRedln.GetRedlineData().Next(); + const SwRedlineDataChild *pBackupData = pParent->pNext; + + if (!pRedlineData && pBackupData) + { + // Redline-Children were deleted + if ((i = CalcDiff(i, true)) == SwRedlineTable::npos) + return; + continue; + } + else + { + while (pRedlineData) + { + if (pRedlineData != pBackupData->pChild) + { + // Redline-Children were inserted, changed or deleted + if ((i = CalcDiff(i, true)) == SwRedlineTable::npos) + return; + continue; + } + 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(); + 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) + { + if (pParent->xTLBParent) + { + // update only comment + const OUString& sComment(rRedln.GetComment()); + rTreeView.set_text(*pParent->xTLBParent, sComment.replace('\n', ' '), 3); + } + pParent->sComment = rRedln.GetComment(); + } + } + + InitAuthors(); +} + +SwRedlineTable::size_type SwRedlineAcceptDlg::CalcDiff(SwRedlineTable::size_type nStart, bool bChild) +{ + if (!nStart) + { + Init(); + return SwRedlineTable::npos; + } + + weld::TreeView& rTreeView = m_pTable->GetWidget(); + rTreeView.freeze(); + SwView *pView = ::GetActiveView(); + SwWrtShell* pSh = pView->GetWrtShellPtr(); + 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(pParent->pNext); + SwRedlineDataChild* pNext; + + while (pBackupData) + { + pNext = const_cast(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& 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) + { + // insert entries from nStart to i-1 + InsertParents(nStart, i - 1); + rTreeView.thaw(); + 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 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(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 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 xChild(rTreeView.make_iterator()); + OUString sId(OUString::number(reinterpret_cast(pData.release()))); + rTreeView.insert(pParent->xTLBParent.get(), -1, nullptr, &sId, nullptr, nullptr, + nullptr, false, xChild.get()); + + 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) +{ + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + SwRedlineTable::size_type nCount = pSh->GetRedlineCount(); + + std::vector aLBoxArr; + + weld::TreeView& rTreeView = m_pTable->GetWidget(); + + // because of Bug of TLB that ALWAYS calls the SelectHandler at Remove: + rTreeView.connect_changed(Link()); + + 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(m_RedlineParents[i]->pNext); + auto it = std::find_if(m_RedlineChildren.begin(), m_RedlineChildren.end(), + [&pChildPtr](const std::unique_ptr& rChildPtr) { return rChildPtr.get() == pChildPtr; }); + if (it != m_RedlineChildren.end()) + { + sal_uInt16 nChildren = 0; + while (pChildPtr) + { + pChildPtr = const_cast(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(); + SwWrtShell* pSh = pView->GetWrtShellPtr(); + bool bHasRedlineAutoFormat = HasRedlineAutoFormat(); + + SwRedlineTable::size_type nCount = pSh->GetRedlineCount(); + nEnd = std::min(nEnd, (nCount - 1)); // also treats nEnd=SwRedlineTable::npos (until the end) + + 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(); + if( nullptr == (pCurrRedline = pSh->SelNextRedline())) + pCurrRedline = pSh->SelPrevRedline(); + pSh->SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent); + } + } + else + pCurrRedline = nullptr; + + rTreeView.freeze(); + if (m_pTable->IsSorted()) + rTreeView.make_unsorted(); + for (SwRedlineTable::size_type i = nStart; i <= nEnd; i++) + { + const SwRangeRedline& rRedln = pSh->GetRedline(i); + const SwRedlineData *pRedlineData = &rRedln.GetRedlineData(); + + pRedlineParent = new SwRedlineDataParent; + pRedlineParent->pData = pRedlineData; + pRedlineParent->pNext = nullptr; + const OUString& sComment(rRedln.GetComment()); + pRedlineParent->sComment = sComment.replace('\n', ' '); + m_RedlineParents.insert(m_RedlineParents.begin() + i, + std::unique_ptr(pRedlineParent)); + + std::unique_ptr pData(new RedlinData); + pData->pData = pRedlineParent; + pData->bDisabled = false; + + OUString sImage = GetActionImage(rRedln); + OUString sAuthor = rRedln.GetAuthorString(0); + pData->aDateTime = rRedln.GetTimeStamp(0); + pData->eType = rRedln.GetType(0); + OUString sDateEntry = GetAppLangDateTimeString(pData->aDateTime); + + OUString sId = OUString::number(reinterpret_cast(pData.release())); + std::unique_ptr xParent(rTreeView.make_iterator()); + rTreeView.insert(nullptr, i, nullptr, &sId, nullptr, nullptr, nullptr, false, xParent.get()); + + 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 ) +{ + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + int nPos = -1; + + typedef std::vector> 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 = reinterpret_cast(rTreeView.get_id(rEntry).toInt64()); + + 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(); + + if (aRedlines.size() > 1) + { + 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 ); + } + + if (aRedlines.size() > 1) + { + 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) +{ + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + weld::TreeView& rTreeView = m_pTable->GetWidget(); + return pSh->FindRedlineOfData( *static_cast(reinterpret_cast( + rTreeView.get_id(rEntry).toInt64())->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) +{ + SwView * pView = ::GetActiveView(); + pView->GetViewFrame()->GetDispatcher()-> + Execute(SID_UNDO, SfxCallMode::SYNCHRON); + m_pTPView->EnableUndo(pView->GetSlotState(SID_UNDO) != nullptr); + + 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) +{ + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + m_aSelectTimer.Stop(); + + 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 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(); + } + } + return false; + }); + + pSh->LeaveAddMode(); + pSh->EndAction(); + SwViewShell::SetCareDialog(nullptr); + } + } + + bool bEnable = !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->EnableRejectAll( bEnable ); + m_pTPView->EnableClearFormatAll( bEnable && m_bOnlyFormatedRedlines ); +} + +IMPL_LINK(SwRedlineAcceptDlg, CommandHdl, const CommandEvent&, rCEvt, bool) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + SwWrtShell* pSh = ::GetActiveView()->GetWrtShellPtr(); + const SwRangeRedline *pRed = nullptr; + + weld::TreeView& rTreeView = m_pTable->GetWidget(); + std::unique_ptr xEntry(rTreeView.make_iterator()); + bool bEntry = rTreeView.get_selected(xEntry.get()); + if (bEntry) + { + std::unique_ptr 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_xPopup->set_active("writersort" + OString::number(i), i == nColumn); + + OString 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(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 pDlg(pFact->CreateSvxPostItDialog(&rTreeView, aSet)); + + pDlg->HideAuthor(); + + const char* pResId = nullptr; + 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 = sCommand.copy(10).toInt32(); + + if (nSortMode == 4 && nColumn == 4) + return true; // we already have it + if (nSortMode == 4) + nSortMode = -1; // unsorted / sorted by position + + SwWait aWait( *::GetActiveView()->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, ""); + aStr = aStr.copy(n1 - nPos + 1); + } + } + } + return aStr; + } +} + +void SwRedlineAcceptDlg::Initialize(OUString& rExtraString) +{ + if (!rExtraString.isEmpty()) + { + OUString aStr = lcl_StripAcceptChgDat(rExtraString); + if (!aStr.isEmpty()) + { + int nCount = aStr.toInt32(); + if (nCount > 2) + { + std::vector 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 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 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(vcl::Window* pParent, const css::uno::Reference& rFrame) + : PanelLayout(pParent, "ManageChangesPanel", "modules/swriter/ui/managechangessidebar.ui", rFrame) + , 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() +{ + disposeOnce(); +} + +void SwRedlineAcceptPanel::dispose() +{ + mpImplDlg.reset(); + mxContentArea.reset(); + PanelLayout::dispose(); +} + +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 000000000..680031a26 --- /dev/null +++ b/sw/source/uibase/misc/swruler.cxx @@ -0,0 +1,371 @@ +/* -*- 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, long nX, long nY, long nSize, + const Color& rColor, bool bCollapsed) +{ + tools::Polygon aTriaglePolygon(4); + + if (bCollapsed) + { + if (AllSettings::GetLayoutRTL()) // < + { + aTriaglePolygon.SetPoint({ nX + nSize / 2, nY }, 0); + aTriaglePolygon.SetPoint({ nX + nSize / 2, nY + nSize }, 1); + aTriaglePolygon.SetPoint({ nX, nY + nSize / 2 }, 2); + aTriaglePolygon.SetPoint({ nX + nSize / 2, nY }, 3); + } + else // > + { + aTriaglePolygon.SetPoint({ nX, nY }, 0); + aTriaglePolygon.SetPoint({ nX + nSize / 2, nY + nSize / 2 }, 1); + aTriaglePolygon.SetPoint({ nX, nY + nSize }, 2); + aTriaglePolygon.SetPoint({ nX, nY }, 3); + } + } + else // v + { + aTriaglePolygon.SetPoint({ nX, nY + nSize / 2 }, 0); + aTriaglePolygon.SetPoint({ nX + nSize, nY + nSize / 2 }, 1); + aTriaglePolygon.SetPoint({ nX + nSize / 2, nY + nSize }, 2); + aTriaglePolygon.SetPoint({ nX, nY + nSize / 2 }, 3); + } + + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(rColor); + rRenderContext.DrawPolygon(aTriaglePolygon); +} +} + +// 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) + , mnFadeRate(0) + , maVirDev(VclPtr::Create(*this)) +{ + // Set fading timeout: 5 x 40ms = 200ms + maFadeTimer.SetTimeout(40); + maFadeTimer.SetInvokeHandler(LINK(this, SwCommentRuler, FadeHandler)); + maFadeTimer.SetDebugName("sw::SwCommentRuler maFadeTimer"); + + // 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 long nTriangleSize = maVirDev->GetTextHeight() / 2 + 1; + const 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 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().IsInside(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().IsInside(aMousePos); + if (mbIsHighlighted != bWasHighlighted) + // Do start fading + maFadeTimer.Start(); +} + +void SwCommentRuler::MouseButtonDown(const MouseEvent& rMEvt) +{ + Point aMousePos = rMEvt.GetPosPixel(); + if (!rMEvt.IsLeft() || IsTracking() || !GetCommentControlRegion().IsInside(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(); +} + +std::string SwCommentRuler::CreateJsonNotification() +{ + boost::property_tree::ptree jsonNotif; + + // 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. + jsonNotif.put("margin1", convertTwipToMm100(GetMargin1())); + jsonNotif.put("margin2", convertTwipToMm100(GetMargin2())); + jsonNotif.put("leftOffset", convertTwipToMm100(GetNullOffset())); + jsonNotif.put("pageOffset", convertTwipToMm100(GetPageOffset())); + + // GetPageWidth() on the other hand does return a value in twips. + // So here convertTwipToMm100() really does produce actual mm100. Fun. + jsonNotif.put("pageWidth", convertTwipToMm100(GetPageWidth())); + + boost::property_tree::ptree 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()) + { + boost::property_tree::ptree element; + element.put("position", convertTwipToMm100(tab.nPos)); + element.put("style", tab.nStyle); + tabs.push_back(std::make_pair("", element)); + } + + jsonNotif.add_child("tabs", tabs); + + RulerUnitData aUnitData = GetCurrentRulerUnit(); + jsonNotif.put("unit", aUnitData.aUnitStr); + + std::stringstream aStream; + boost::property_tree::write_json(aStream, jsonNotif); + return aStream.str(); +} + +void SwCommentRuler::NotifyKit() +{ + if (!comphelper::LibreOfficeKit::isActive()) + return; + + const std::string test = CreateJsonNotification(); + mpViewShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_RULER_UPDATE, + test.c_str()); +} + +void SwCommentRuler::Update() +{ + tools::Rectangle aPreviousControlRect = GetCommentControlRegion(); + SvxRuler::Update(); + if (aPreviousControlRect != GetCommentControlRegion()) + Invalidate(); + NotifyKit(); +} + +void SwCommentRuler::UpdateCommentHelpText() +{ + const char* 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 unsigned long nSidebarWidth = pPostItMgr->GetSidebarWidth(true); + + //FIXME When the page width is larger then screen, the ruler is misplaced by one pixel + 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 + long nTop = 4; + // Somehow pPostItMgr->GetSidebarBorderWidth() returns border width already doubled + long nRight = nLeft + nSidebarWidth + pPostItMgr->GetSidebarBorderWidth(true); + 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 000000000..16625a4df --- /dev/null +++ b/sw/source/uibase/ribbar/conarc.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 +#include +#include + +#include +#include +#include +#include +#include + +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(OBJ_CARC); + break; + case SID_DRAW_PIE: + m_pWin->SetSdrDrawMode(OBJ_SECT); + break; + case SID_DRAW_CIRCLECUT: + m_pWin->SetSdrDrawMode(OBJ_CCUT); + break; + default: + m_pWin->SetSdrDrawMode(OBJ_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 000000000..a90652f1b --- /dev/null +++ b/sw/source/uibase/ribbar/concustomshape.cxx @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace com::sun::star; + +ConstCustomShape::ConstCustomShape( SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView, SfxRequest const & rReq ) + : SwDrawBase( pWrtShell, pEditWin, pSwView ) +{ + aCustomShape = ConstCustomShape::GetShapeTypeFromRequest( rReq ); +} + +const OUString& ConstCustomShape::GetShapeType() const +{ + return aCustomShape; +} + +OUString ConstCustomShape::GetShapeTypeFromRequest( SfxRequest const & rReq ) +{ + OUString aRet; + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + const SfxStringItem& rItm = static_cast(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(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( OBJ_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::size_type i = 0; i < aObjList.size(); i++ ) + { + if ( aObjList[ i ].equalsIgnoreAsciiCase( 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(); + SfxItemSet aDest( + pObj->getSdrModelFromSdrObject().GetItemPool(), + svl::Items< + // 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.Set( rSource ); + pObj->SetMergedItemSet( aDest ); + sal_Int32 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + { + double a = nAngle * F_PI18000; + pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) ); + } + 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(pObj)->MergeDefaultAttributes( &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 ); + } + } +} + +// #i33136# +bool ConstCustomShape::doConstructOrthogonal() const +{ + return SdrObjCustomShape::doConstructOrthogonal(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 000000000..a61a0d725 --- /dev/null +++ b/sw/source/uibase/ribbar/conform.cxx @@ -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 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +ConstFormControl::ConstFormControl(SwWrtShell* pWrtShell, SwEditWin* pEditWin, SwView* pSwView) : + SwDrawBase(pWrtShell, pEditWin, pSwView) +{ + 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( static_cast< sal_uInt16 >(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( static_cast(nSlotId) ); + SwDrawBase::Activate(nSlotId); + m_pSh->GetDrawView()->SetCurrentObj(nSlotId); + + m_pWin->SetPointer(PointerStyle::DrawRect); +} + +void ConstFormControl::CreateDefaultObject() +{ + Point aStartPos(GetDefaultCenterPos()); + Point aEndPos(aStartPos); + aStartPos.AdjustX( -(2 * MM50) ); + aStartPos.AdjustY( -(MM50) ); + aEndPos.AdjustX(2 * MM50 ); + aEndPos.AdjustY(MM50 ); + + if(!m_pSh->HasDrawView()) + m_pSh->MakeDrawView(); + + SdrView *pSdrView = m_pSh->GetDrawView(); + pSdrView->SetDesignMode(); + m_pSh->BeginCreate( static_cast< sal_uInt16 >(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 000000000..481722734 --- /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 +#include + +#include +#include +#include +#include +#include + +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() != OBJ_FREELINE && + m_pWin->GetSdrDrawMode() != OBJ_FREEFILL) + { + 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(OBJ_PLIN); + break; + + case SID_DRAW_POLYGON: + case SID_DRAW_XPOLYGON: + m_pWin->SetSdrDrawMode(OBJ_POLY); + break; + + case SID_DRAW_BEZIER_NOFILL: + m_pWin->SetSdrDrawMode(OBJ_PATHLINE); + break; + + case SID_DRAW_BEZIER_FILL: + m_pWin->SetSdrDrawMode(OBJ_PATHFILL); + break; + + case SID_DRAW_FREELINE_NOFILL: + m_pWin->SetSdrDrawMode(OBJ_FREELINE); + break; + + case SID_DRAW_FREELINE: + m_pWin->SetSdrDrawMode(OBJ_FREEFILL); + 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 000000000..3484c4a55 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +ConstRectangle::ConstRectangle( SwWrtShell* pWrtShell, SwEditWin* pEditWin, + SwView* pSwView ) + : SwDrawBase( pWrtShell, pEditWin, pSwView ) + , bMarquee(false) + , bCapVertical(false) + , mbVertical(false) +{ +} + +bool ConstRectangle::MouseButtonDown(const MouseEvent& rMEvt) +{ + bool bReturn = SwDrawBase::MouseButtonDown(rMEvt); + + if (bReturn) + { + if (m_pWin->GetSdrDrawMode() == OBJ_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 OBJ_TEXT: + if( bMarquee ) + { + m_pSh->ChgAnchor(RndStdIds::FLY_AS_CHAR); + + if( pObj ) + { + // Set the attributes needed for scrolling + SfxItemSet aItemSet( pSdrView->GetModel()->GetItemPool(), + svl::Items{}); + + 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(m_pWin->PixelToLogic(Size(2,1)).Width())) ); + + pObj->SetMergedItemSetAndBroadcast(aItemSet); + } + } + else if(mbVertical) + { + if (SdrTextObj* pText = dynamic_cast(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 OBJ_CAPTION: + { + SdrCaptionObj* pCaptObj = dynamic_cast(pObj); + if( bCapVertical && pCaptObj ) + { + pCaptObj->ForceOutlinerParaObject(); + OutlinerParaObject* pOPO = pCaptObj->GetOutlinerParaObject(); + if( pOPO && !pOPO->IsVertical() ) + pOPO->SetVertical( true ); + } + } + break; + default:; //prevent warning + } + } + return bRet; +} + +void ConstRectangle::Activate(const sal_uInt16 nSlotId) +{ + bMarquee = 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(OBJ_LINE); + break; + + case SID_DRAW_MEASURELINE: + m_pWin->SetSdrDrawMode(OBJ_MEASURE); + break; + + case SID_DRAW_RECT: + m_pWin->SetSdrDrawMode(OBJ_RECT); + break; + + case SID_DRAW_ELLIPSE: + m_pWin->SetSdrDrawMode(OBJ_CIRC); + break; + + case SID_DRAW_TEXT_MARQUEE: + bMarquee = true; + m_pWin->SetSdrDrawMode(OBJ_TEXT); + break; + + case SID_DRAW_TEXT_VERTICAL: + mbVertical = true; + m_pWin->SetSdrDrawMode(OBJ_TEXT); + break; + + case SID_DRAW_TEXT: + m_pWin->SetSdrDrawMode(OBJ_TEXT); + break; + + case SID_DRAW_CAPTION_VERTICAL: + bCapVertical = true; + [[fallthrough]]; + case SID_DRAW_CAPTION: + m_pWin->SetSdrDrawMode(OBJ_CAPTION); + break; + + default: + m_pWin->SetSdrDrawMode(OBJ_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 000000000..f2b13d8d1 --- /dev/null +++ b/sw/source/uibase/ribbar/drawbase.cxx @@ -0,0 +1,550 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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( static_cast< sal_uInt16 >(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.pHdl->GetKind() == SdrHdlKind::BezierWeight) + { + // Drag handle + g_bNoInterrupt = true; + bReturn = pSdrView->BegDragObj(m_aStartPos, nullptr, aVEvt.pHdl); + 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.pHdl) || rMEvt.IsShift())) + { + SdrHdl* pHdl = nullptr; + + if (!rMEvt.IsShift()) + { + pSdrView->UnmarkAllPoints(); + pHdl = pSdrView->PickHandle(m_aStartPos); + } + else + { + if (pSdrView->IsPointMarked(*aVEvt.pHdl)) + { + bReturn = pSdrView->UnmarkPoint(*aVEvt.pHdl); + 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 = OBJ_PLIN == nDrawMode || + OBJ_POLY == nDrawMode || + OBJ_PATHLINE == nDrawMode || + OBJ_PATHFILL == nDrawMode || + OBJ_FREELINE == nDrawMode || + OBJ_FREEFILL == nDrawMode; + if(rMEvt.IsRight() || (aPnt == m_aStartPos && !bMultiPoint)) + { + m_pSh->BreakCreate(); + m_pView->LeaveDrawCreate(); + } + else + { + if (OBJ_NONE == nDrawMode) + { + SwRewriter aRewriter; + + aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME)); + m_pSh->StartUndo(SwUndoId::INSERT, &aRewriter); + } + + m_pSh->EndCreate(SdrCreateCmd::ForceEnd); + if (OBJ_NONE == 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(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) + { + SfxItemSet aSet(m_pView->GetPool(),svl::Items{}); + 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->IsAutoUpdateFormat()) + m_pSh->AutoUpdateFrame(pFormat, aSet); + else + m_pSh->SetFlyFrameAttr( aSet ); + } + } + if (m_pWin->GetSdrDrawMode() == OBJ_NONE) + { + 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( static_cast< sal_uInt16 >(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()) + { + 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() +{ + Point aStartPos = GetDefaultCenterPos(); + Point aEndPos(aStartPos); + aStartPos.AdjustX( -(6 * MM50) ); + aStartPos.AdjustY( -(6 * MM50) ); + aEndPos.AdjustX(6 * MM50 ); + aEndPos.AdjustY(6 * MM50 ); + tools::Rectangle aRect(aStartPos, aEndPos); + m_pSh->CreateDefaultShape( static_cast< sal_uInt16 >(m_pWin->GetSdrDrawMode()), aRect, m_nSlotId); +} + +Point SwDrawBase::GetDefaultCenterPos() const +{ + Size aDocSz(m_pSh->GetDocSize()); + + SwRect aVisArea(m_pSh->VisArea()); + if (comphelper::LibreOfficeKit::isActive()) + { + aVisArea = m_pSh->getLOKVisibleArea(); + aVisArea.Intersection(SwRect(Point(), aDocSz)); + } + + Point aCenter = aVisArea.Center(); + if (aVisArea.Width() > aDocSz.Width()) + 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 000000000..a70583fda --- /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 +#include +#include +#include +#include +#include +#include +#include + +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(OBJ_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 000000000..841dc4a82 --- /dev/null +++ b/sw/source/uibase/ribbar/inputwin.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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Only for the UpdateRange: Delete the box in which the stacked cursor is positioned. +#include + +#include + +#include + +#define ED_POS 2 +#define ED_FORMULA 3 + +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::Create(this)) + , mxEdit(VclPtr::Create(this)) + , pWrtShell(nullptr) + , pView(nullptr) + , m_bDoesUndo(true) + , m_bResetUndo(false) + , m_bCallUndo(false) +{ + bFirst = true; + bIsTable = 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(pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr); + SwView* pActiveView = ::GetActiveView(); + if (pDispatcherView == pActiveView) + pView = pActiveView; + pWrtShell = pView ? 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) ); + 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(pView) + { + pView->GetHRuler().SetActive(); + pView->GetVRuler().SetActive(); + } + pMgr.reset(); + if(pWrtShell) + pWrtShell->EndSelTableCells(); + + CleanupUglyHackWithUndo(); + + mxPos.disposeAndClear(); + mxEdit.disposeAndClear(); + ToolBox::dispose(); +} + +void SwInputWindow::CleanupUglyHackWithUndo() +{ + if (m_bResetUndo) + { + if (pWrtShell) + { + DelBoxContent(); + pWrtShell->DoUndo(m_bDoesUndo); + if (m_bCallUndo) + { + pWrtShell->Undo(); + } + } + m_bResetUndo = false; // #i117122# once is enough :) + } +} + +void SwInputWindow::Resize() +{ + ToolBox::Resize(); + + long nWidth = GetSizePixel().Width(); + long nLeft = mxEdit->GetPosPixel().X(); + Size aEditSize = mxEdit->GetSizePixel(); + + aEditSize.setWidth( std::max( static_cast(nWidth - nLeft - 5), long(0) ) ); + mxEdit->SetSizePixel( aEditSize ); +} + +void SwInputWindow::ShowWin() +{ + bIsTable = false; + // stop rulers + if (pView) + { + pView->GetHRuler().SetActive( false ); + pView->GetVRuler().SetActive( false ); + + OSL_ENSURE(pWrtShell, "no WrtShell!"); + // Cursor in table + bIsTable = pWrtShell->IsCursorInTable(); + + if( bFirst ) + pWrtShell->SelTableCells( LINK( this, SwInputWindow, + SelTableCellsNotify) ); + if( bIsTable ) + { + const OUString& rPos = pWrtShell->GetBoxNms(); + sal_Int32 nPos = 0; + short nSrch = -1; + while( (nPos = rPos.indexOf( ':',nPos + 1 ) ) != -1 ) + nSrch = static_cast(nPos); + mxPos->set_text( rPos.copy( ++nSrch ) ); + aCurrentTableName = pWrtShell->GetTableFormat()->GetName(); + } + else + mxPos->set_text(SwResId(STR_TBL_FORMULA)); + + // Edit current field + OSL_ENSURE(pMgr == nullptr, "FieldManager not deleted"); + pMgr.reset(new SwFieldMgr); + + // Form should always begin with "=" , so set here + OUString sEdit('='); + if( pMgr->GetCurField() && SwFieldTypesEnum::Formel == pMgr->GetCurTypeId() ) + { + sEdit += pMgr->GetCurFieldPar2(); + } + else if( bFirst && bIsTable ) + { + m_bResetUndo = true; + SAL_WARN_IF( + officecfg::Office::Common::Undo::Steps::get() <= 0, + "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0"); + + m_bDoesUndo = pWrtShell->DoesUndo(); + if( !m_bDoesUndo ) + { + pWrtShell->DoUndo(); + } + + if( !pWrtShell->SwCursorShell::HasSelection() ) + { + pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); + pWrtShell->SetMark(); + pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); + } + if( pWrtShell->SwCursorShell::HasSelection() ) + { + pWrtShell->StartUndo( SwUndoId::DELETE ); + pWrtShell->Delete(); + if( SwUndoId::EMPTY != pWrtShell->EndUndo( SwUndoId::DELETE )) + { + m_bCallUndo = true; + } + } + pWrtShell->DoUndo(false); + + SfxItemSet aSet( pWrtShell->GetAttrPool(), svl::Items{} ); + if( pWrtShell->GetTableBoxFormulaAttrs( aSet )) + sEdit += aSet.Get( RES_BOXATR_FORMULA ).GetFormula(); + } + + if( bFirst ) + { + // Set WrtShell flags correctly + pWrtShell->SttSelect(); + pWrtShell->EndSelect(); + } + + bFirst = false; + + mxEdit->connect_changed( LINK( this, SwInputWindow, ModifyHdl )); + + mxEdit->set_text( sEdit ); + sOldFormula = sEdit; + + // For input cut the UserInterface + + pView->GetEditWin().LockKeyInput(true); + pView->GetViewFrame()->GetDispatcher()->Lock(true); + pWrtShell->Push(); + } + + ToolBox::Show(); + + // grab focus after ToolBox is shown so focus isn't potentially lost elsewhere + if (pView) + { + int nPos = mxEdit->get_text().getLength(); + mxEdit->select_region(nPos, nPos); + mxEdit->GrabFocus(); + } +} + +IMPL_LINK( SwInputWindow, MenuHdl, Menu *, pMenu, bool ) +{ + OString aCommand = pMenu->GetCurItemIdent(); + if (!aCommand.isEmpty()) + { + aCommand += " "; + mxEdit->replace_selection(OStringToOUString(aCommand, RTL_TEXTENCODING_ASCII_US)); + } + return false; +} + +IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl, ToolBox *, void) +{ + sal_uInt16 nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + if (nCurID == FN_FORMULA_CALC) + { + VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/swriter/ui/inputwinmenu.ui", ""); + VclPtr aPopMenu(aBuilder.get_menu("menu")); + aPopMenu->SetSelectHdl(LINK(this, SwInputWindow, MenuHdl)); + aPopMenu->Execute(this, GetItemRect(FN_FORMULA_CALC), PopupMenuFlags::NoMouseUpClose); + } +} + +void SwInputWindow::Click( ) +{ + sal_uInt16 nCurID = GetCurItemId(); + EndSelection(); // reset back CurItemId ! + switch ( nCurID ) + { + case FN_FORMULA_CANCEL: + { + CancelFormula(); + } + break; + case FN_FORMULA_APPLY: + { + ApplyFormula(); + } + break; + } +} + +void SwInputWindow::ApplyFormula() +{ + pView->GetViewFrame()->GetDispatcher()->Lock(false); + pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + 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); + + pWrtShell->EndSelTableCells(); + pView->GetEditWin().GrabFocus(); + const SfxPoolItem* aArgs[2]; + aArgs[0] = &aParam; + aArgs[1] = nullptr; + pView->GetViewFrame()->GetBindings().Execute( FN_EDIT_FORMULA, aArgs, SfxCallMode::ASYNCHRON ); +} + +void SwInputWindow::CancelFormula() +{ + if(pView) + { + pView->GetViewFrame()->GetDispatcher()->Lock( false ); + pView->GetEditWin().LockKeyInput(false); + CleanupUglyHackWithUndo(); + pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + + if( bDelSel ) + pWrtShell->EnterStdMode(); + + pWrtShell->EndSelTableCells(); + + pView->GetEditWin().GrabFocus(); + + 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(bIsTable) + { + SwFrameFormat* pTableFormat = rCaller.GetTableFormat(); + OUString sBoxNms( rCaller.GetBoxNms() ); + OUString sTableNm; + if( pTableFormat && aCurrentTableName != pTableFormat->GetName() ) + sTableNm = pTableFormat->GetName(); + + mxEdit->UpdateRange( sBoxNms, sTableNm ); + + OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() + + OUStringChar(CH_PDF); + + if( sNew != 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! + pWrtShell->StartAllAction(); + + SwPaM aPam( *pWrtShell->GetStackCursor()->GetPoint() ); + aPam.Move( fnMoveBackward, GoInSection ); + aPam.SetMark(); + aPam.Move( fnMoveForward, GoInSection ); + + IDocumentContentOperations& rIDCO = pWrtShell->getIDocumentContentOperations(); + rIDCO.DeleteRange( aPam ); + rIDCO.InsertString( aPam, sNew ); + pWrtShell->EndAllAction(); + 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()); + bDelSel = true; +} + +IMPL_LINK_NOARG(SwInputWindow, ModifyHdl, weld::Entry&, void) +{ + if (bIsTable && m_bResetUndo) + { + pWrtShell->StartAllAction(); + DelBoxContent(); + OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text() + + OUStringChar(CH_PDF); + pWrtShell->SwEditShell::Insert2( sNew ); + pWrtShell->EndAllAction(); + sOldFormula = sNew; + } +} + +void SwInputWindow::DelBoxContent() +{ + if( bIsTable ) + { + pWrtShell->StartAllAction(); + pWrtShell->ClearMark(); + pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + pWrtShell->Push(); + pWrtShell->MoveSection( GoCurrSection, fnSectionStart ); + pWrtShell->SetMark(); + pWrtShell->MoveSection( GoCurrSection, fnSectionEnd ); + pWrtShell->SwEditShell::Delete(); + 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(GetParent())->CancelFormula(); + bHandled = true; + } + return bHandled || ChildKeyInput(rEvent); +} + +IMPL_LINK_NOARG(InputEdit, ActivateHdl, weld::Entry&, bool) +{ + static_cast(GetParent())->ApplyFormula(); + return true; +} + +void InputEdit::UpdateRange(const OUString& rBoxes, + const OUString& rName ) +{ + if( rBoxes.isEmpty() ) + { + 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 = static_cast(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()[ static_cast(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 = static_cast(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()) && + static_cast(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 = static_cast(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 ) +{ + pDispatch = pBindings->GetDispatcher(); + SetWindow(VclPtr::Create(_pParent, pDispatch)); + static_cast(GetWindow())->ShowWin(); + SetAlignment(SfxChildAlignment::LOWESTTOP); +} + +SwInputChild::~SwInputChild() +{ + if(pDispatch) + 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 000000000..3e93d5320 --- /dev/null +++ b/sw/source/uibase/ribbar/workctrl.cxx @@ -0,0 +1,1063 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Size check +#define NAVI_ENTRIES 18 + +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, + sal_uInt16 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 aLnk = LINK(this, SwTbxAutoTextCtrl, PopupHdl); + + ScopedVclPtrInstance pPopup; + SwGlossaryList* pGlossaryList = ::GetGlossaryList(); + const size_t nGroupCount = pGlossaryList->GetGroupCount(); + for(size_t i = 1; i <= nGroupCount; ++i) + { + OUString sTitle = pGlossaryList->GetGroupTitle(i - 1); + const sal_uInt16 nBlockCount = pGlossaryList->GetBlockCount(i -1); + if(nBlockCount) + { + sal_uInt16 nIndex = static_cast(100*i); + // but insert without extension + pPopup->InsertItem( i, sTitle); + VclPtrInstance 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(); + sal_uInt16 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::StateChanged( 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); + + SwGlossaryHdl* pGlosHdl = ::GetActiveView()->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 +}; + +static OUStringLiteral const 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 +}; + +static const char* aNavigationStrIds[ NAVI_ENTRIES ] = +{ + ST_TBL, + ST_FRM, + ST_GRF, + ST_OLE, + ST_PGE, + ST_OUTL, + ST_MARK, + ST_DRW, + ST_CTRL, + ST_REG, + ST_BKM, + ST_SEL, + ST_FTN, + ST_POSTIT, + ST_SRCH_REP, + ST_INDEX_ENTRY, + ST_TABLE_FORMULA, + ST_TABLE_FORMULA_ERROR +}; + +// these are global strings +static const char* 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_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 +}; + +static OUString lcl_GetScrollToolTip(bool bNext) +{ + sal_uInt16 nResId = SwView::GetMoveType(); + if (!bNext) + nResId += NID_COUNT; + const char* id = STR_IMGBTN_ARY[nResId - NID_START]; + return id ? SwResId(id): OUString(); +} + +namespace { + +class SwZoomBox_Impl final : public InterimItemWindow +{ + std::unique_ptr m_xWidget; + sal_uInt16 nSlotId; + bool 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(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + 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")) + , nSlotId(nSlot) + , bRelease(true) +{ + 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 char* const 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 char* 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 == 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 = static_cast(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()); + } + + 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: + 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 ( !bRelease ) + { + 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, + sal_uInt16 nId, + ToolBox& rTbx) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SwPreviewZoomControl::~SwPreviewZoomControl() +{ +} + +void SwPreviewZoomControl::StateChanged( sal_uInt16 /*nSID*/, + SfxItemState eState, + const SfxPoolItem* pState ) +{ + sal_uInt16 nId = GetId(); + GetToolBox().EnableItem( nId, (GetItemState(pState) != SfxItemState::DISABLED) ); + SwZoomBox_Impl* pBox = static_cast(GetToolBox().GetItemWindow( GetId() )); + if(SfxItemState::DEFAULT <= eState) + { + OUString sZoom(unicode::formatPercent(static_cast(pState)->GetValue(), + Application::GetSettings().GetUILanguageTag())); + pBox->set_entry_text(sZoom); + pBox->save_value(); + } +} + +VclPtr SwPreviewZoomControl::CreateItemWindow( vcl::Window *pParent ) +{ + VclPtrInstance pRet( pParent, GetSlotId() ); + return pRet.get(); +} + +namespace { + +class SwJumpToSpecificBox_Impl final : public InterimItemWindow +{ + std::unique_ptr m_xWidget; + + sal_uInt16 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 void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + 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")) + , nSlotId(nSlot) +{ + 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(nSlotId); + aPageNum.SetValue(static_cast(sEntry.toInt32())); + SfxObjectShell* pCurrentShell = SfxObjectShell::Current(); + pCurrentShell->GetDispatcher()->ExecuteList(nSlotId, SfxCallMode::ASYNCHRON, + { &aPageNum }); + return true; +} + +SFX_IMPL_TOOLBOX_CONTROL( SwJumpToSpecificPageControl, SfxUInt16Item); + +SwJumpToSpecificPageControl::SwJumpToSpecificPageControl( + sal_uInt16 nSlotId, + sal_uInt16 nId, + ToolBox& rTbx) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{} + +SwJumpToSpecificPageControl::~SwJumpToSpecificPageControl() +{} + +VclPtr SwJumpToSpecificPageControl::CreateItemWindow( vcl::Window *pParent ) +{ + VclPtrInstance pRet( pParent, GetSlotId() ); + return pRet.get(); +} + +namespace { + +class NavElementBox_Base; +class NavElementBox_Impl; + +class NavElementToolBoxControl : public svt::ToolboxController, + public lang::XServiceInfo +{ + public: + explicit NavElementToolBoxControl( + const css::uno::Reference< css::uno::XComponentContext >& rServiceManager ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () 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; + + // 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; + + void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs ); + using svt::ToolboxController::dispatchCommand; + + private: + VclPtr m_xVclBox; + std::unique_ptr m_xWeldBox; + NavElementBox_Base* m_pBox; +}; + +class NavElementBox_Base +{ +public: + NavElementBox_Base(std::unique_ptr xWidget, + const uno::Reference& _xFrame, + NavElementToolBoxControl& rCtrl); + + virtual ~NavElementBox_Base() + { + } + + void set_sensitive(bool bSensitive) + { + m_xWidget->set_sensitive(bSensitive); + } + + void UpdateBox(); + +protected: + std::unique_ptr m_xWidget; + NavElementToolBoxControl* m_pCtrl; + bool m_bRelease; + uno::Reference< frame::XFrame > m_xFrame; + + virtual bool DoKeyInput(const KeyEvent& rKEvt); + + DECL_LINK(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& _xFrame, + NavElementToolBoxControl& rCtrl); + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + virtual bool DoKeyInput(const KeyEvent& rKEvt) override; + + virtual ~NavElementBox_Impl() override + { + disposeOnce(); + } +}; + +} + +NavElementBox_Base::NavElementBox_Base( + std::unique_ptr xWidget, + const uno::Reference< frame::XFrame >& _xFrame, + NavElementToolBoxControl& _rCtrl ) + : m_xWidget(std::move(xWidget)) + , m_pCtrl(&_rCtrl) + , m_bRelease(true) + , m_xFrame(_xFrame) +{ + m_xWidget->set_size_request(150, -1); + + m_xWidget->make_sorted(); + m_xWidget->freeze(); + for (sal_uInt16 i = 0; i < NID_COUNT; i++) + m_xWidget->append(OUString::number(aNavigationInsertIds[i]), SwResId(aNavigationStrIds[i]), aNavigationImgIds[i]); + m_xWidget->thaw(); + + m_xWidget->connect_changed(LINK(this, NavElementBox_Base, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, NavElementBox_Base, KeyInputHdl)); +} + +NavElementBox_Impl::NavElementBox_Impl( + vcl::Window* _pParent, + const uno::Reference< frame::XFrame >& _xFrame, + NavElementToolBoxControl& _rCtrl ) + : InterimItemWindow(_pParent, "modules/swriter/ui/combobox.ui", "ComboBox") + , NavElementBox_Base(m_xBuilder->weld_combo_box("combobox"), _xFrame, _rCtrl) +{ + SetSizePixel(m_xContainer->get_preferred_size()); +} + +void NavElementBox_Base::ReleaseFocus_Impl() +{ + if ( !m_bRelease ) + { + m_bRelease = true; + return; + } + + if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) + m_xFrame->getContainerWindow()->setFocus(); +} + +IMPL_LINK(NavElementBox_Base, SelectHdl, weld::ComboBox&, rComboBox, void) +{ + if (rComboBox.changed_by_direct_pick()) // only when picked from the list + { + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + + sal_uInt16 nMoveType = rComboBox.get_active_id().toUInt32(); + SwView::SetMoveType( nMoveType ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs; + + /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + ReleaseFocus_Impl(); + + m_pCtrl->dispatchCommand( 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] ) + { + const char* id = aNavigationStrIds[i]; + OUString sText = SwResId( id ); + m_xWidget->set_active_text(sText); + break; + } + } +} + +IMPL_LINK(NavElementBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return DoKeyInput(rKEvt); +} + +bool NavElementBox_Base::DoKeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + + vcl::KeyCode aKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nCode = aKeyCode.GetCode(); + + switch ( nCode ) + { + case KEY_TAB: + { + m_bRelease = false; + SelectHdl(*m_xWidget); + break; + } + case KEY_RETURN: + { + bHandled = true; + SelectHdl(*m_xWidget); + break; + } + case KEY_ESCAPE: + ReleaseFocus_Impl(); + bHandled = true; + break; + } + + return bHandled; +} + +bool NavElementBox_Impl::DoKeyInput(const KeyEvent& rKEvt) +{ + return NavElementBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); +} + + +NavElementToolBoxControl::NavElementToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext ) + : svt::ToolboxController( rxContext, + uno::Reference< frame::XFrame >(), + ".uno:NavElement" ), + m_pBox( nullptr ) +{ +} + +// XInterface +css::uno::Any SAL_CALL NavElementToolBoxControl::queryInterface( const css::uno::Type& aType ) +{ + uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL NavElementToolBoxControl::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL NavElementToolBoxControl::release() throw () +{ + ToolboxController::release(); +} + +// 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) + { + SolarMutexGuard aSolarMutexGuard; + if ( rEvent.FeatureURL.Path == "NavElement" ) + { + if ( rEvent.IsEnabled ) + { + m_pBox->set_sensitive(true); + m_pBox->UpdateBox(); + } + else + m_pBox->set_sensitive(true); + } + } +} + +// 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 xWidget(m_pBuilder->weld_combo_box("NavElementWidget")); + + xItemWindow = css::uno::Reference(new weld::TransportAsXWindow(xWidget.get())); + + m_xWeldBox.reset(new NavElementBox_Base(std::move(xWidget), m_xFrame, *this)); + m_pBox = m_xWeldBox.get(); + } + else + { + VclPtr pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + SolarMutexGuard aSolarMutexGuard; + m_xVclBox = VclPtr::Create( pParent, m_xFrame, *this ); + m_pBox = m_xVclBox.get(); + xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); + } + } + + return xItemWindow; +} + +void NavElementToolBoxControl::dispatchCommand( + const uno::Sequence< beans::PropertyValue >& rArgs ) +{ + uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + util::URL aURL; + uno::Reference< frame::XDispatch > xDispatch; + uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer(); + + aURL.Complete = ".uno:NavElement"; + xURLTransformer->parseStrict( aURL ); + xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aURL, rArgs ); + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_NavElementToolBoxController_get_implementation( + css::uno::XComponentContext *rxContext, + css::uno::Sequence const &) +{ + return cppu::acquire( new NavElementToolBoxControl( rxContext ) ); +} + +namespace { + +class PrevNextScrollToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + enum Type { PREVIOUS, NEXT }; + + PrevNextScrollToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext, Type eType ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () 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; + + // 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 ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + (eType == PREVIOUS) ? OUString( ".uno:ScrollToPrevious" ): OUString( ".uno:ScrollToNext" ) ), + meType( eType ) +{ + addStatusListener(".uno:NavElement"); +} + +// XInterface +css::uno::Any SAL_CALL PrevNextScrollToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL PrevNextScrollToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL PrevNextScrollToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// 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.toUtf8(), lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS)); + else + { + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetQuickHelpText(nId, lcl_GetScrollToolTip(meType != PrevNextScrollToolboxController::PREVIOUS)); + } + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +lo_writer_PreviousScrollToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence 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 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 000000000..5bcda2e9a --- /dev/null +++ b/sw/source/uibase/shells/annotsh.cxx @@ -0,0 +1,1812 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +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 +#include + +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 ) + : rView(r) +{ + SetPool(SwAnnotationShell::GetAnnotationPool(rView)); + SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Annotation)); +} + +SwAnnotationShell::~SwAnnotationShell() +{ +} + +SfxUndoManager* SwAnnotationShell::GetUndoManager() +{ + SwPostItMgr* pPostItMgr = 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 = 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(rReq. + GetArgs()->Get(nSlot))); + aParaMargin.SetWhich( EE_PARA_LRSPACE ); + + aNewAttr.Put(aParaMargin); + rReq.Done(); + break; + } + case SID_ATTR_PARA_LINESPACE: + { + SvxLineSpacingItem aParaMargin = static_cast(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(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 SvxFontListItem* pFontListItem = static_cast< const SvxFontListItem* > + ( SfxObjectShell::Current()->GetItem( SID_ATTR_CHAR_FONTLIST ) ); + 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(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_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(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(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(pItem); + SvxURLField aField(rHLinkItem.GetURL(), rHLinkItem.GetName(), SvxURLFormat::AppDefault); + aField.SetTargetFrame(rHLinkItem.GetTargetFrame()); + + const SvxFieldItem* pFieldItem = pOLV->GetFieldAtSelection(); + + if (pFieldItem && dynamic_cast(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_ZWNBSP : + 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_ZWNBSP: cIns = CHAR_ZWNBSP; 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 (pPostItMgr->GetActiveSidebarWin()->GetLayoutStatus()!=SwPostItHelper::DELETED) + pOLV->InsertText(static_cast(pItem)->GetValue()); + break; + } + case FN_FORMAT_FOOTNOTE_DLG: + { + rView.ExecFormatFootnote(); + break; + } + case FN_NUMBERING_OUTLINE_DLG: + { + rView.ExecNumberingOutline(GetPool()); + rReq.Done(); + } + break; + case SID_OPEN_XML_FILTERSETTINGS: + { + HandleOpenXmlFilterSettings(rReq); + } + break; + case FN_WORDCOUNT_DIALOG: + { + rView.UpdateWordCount(this, nSlot); + break; + } + case SID_CHAR_DLG_EFFECT: + case SID_CHAR_DLG: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxStringItem* pItem = rReq.GetArg(FN_PARAM_1); + + if( !pArgs || pItem ) + { + /* mod + SwView* pView = &GetView(); + FieldUnit eMetric = ::GetDfltMetric(dynamic_cast( pView) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, eMetric)); + */ + SfxItemSet aDlgAttr(GetPool(), svl::Items{}); + + // 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 pDlg(pFact->CreateSwCharDlg(rView.GetFrameWeld(), rView, aDlgAttr, SwCharDlgMode::Ann)); + if (nSlot == SID_CHAR_DLG_EFFECT) + { + pDlg->SetCurPageId("fonteffects"); + } + else if (pItem) + { + pDlg->SetCurPageId(OUStringToOString(pItem->GetValue(), RTL_TEXTENCODING_UTF8)); + } + + 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( pView) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, eMetric)); + */ + SfxItemSet aDlgAttr( + GetPool(), + svl::Items< + EE_ITEMS_START, EE_ITEMS_END, + SID_ATTR_PARA_HYPHENZONE, SID_ATTR_PARA_WIDOWS>{}); + + 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 pDlg(pFact->CreateSwParaDlg(rView.GetFrameWeld(), 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: + { + 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(pPoolItem)->GetValue() ) + bLeftToRight = !bLeftToRight; + } + SfxItemSet aAttr( + *aNewAttr.GetPool(), + svl::Items< + EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR, + EE_PARA_JUST, EE_PARA_JUST>{}); + + SvxAdjust nAdjust = SvxAdjust::Left; + if( SfxItemState::SET == aEditAttr.GetItemState(EE_PARA_JUST, true, &pPoolItem ) ) + nAdjust = static_cast(pPoolItem)->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)); + } + + tools::Rectangle aOutRect = pOLV->GetOutputArea(); + if (tools::Rectangle() != aOutRect && aNewAttr.Count()) + pOLV->SetAttribs(aNewAttr); + + rView.GetViewFrame()->GetBindings().InvalidateAll(false); + if ( pOLV->GetOutliner()->IsModified() ) + 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 = 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(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 SfxPoolItem *pAdjust = nullptr; + aEditAttr.GetItemState( EE_PARA_JUST, false, &pAdjust); + + if( !pAdjust || IsInvalidItem( pAdjust )) + { + rSet.InvalidateItem( nSlotId ); + } + else + { + if ( eAdjust == static_cast(pAdjust)->GetAdjust()) + rSet.Put( SfxBoolItem( nWhich, true )); + else + rSet.InvalidateItem( nWhich ); + } + break; + } + case SID_ATTR_PARA_LINESPACE_10: + 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_15) + nLSpace = 150; + else if (nWhich==SID_ATTR_PARA_LINESPACE_20) + nLSpace = 200; + + const SfxPoolItem *pLSpace = nullptr; + aEditAttr.GetItemState( EE_PARA_SBL, false, &pLSpace ); + + if( !pLSpace || IsInvalidItem( pLSpace )) + { + rSet.InvalidateItem( nSlotId ); + } + else + { + if( nLSpace == static_cast(pLSpace)->GetPropLineSpace() ) + rSet.Put( SfxBoolItem( nWhich, true )); + else + rSet.InvalidateItem( nWhich ); + } + break; + } + case SID_AUTOSPELL_CHECK: + { + const SfxPoolItem* pState = rView.GetSlotState(nWhich); + if (pState) + rSet.Put(SfxBoolItem(nWhich, static_cast(pState)->GetValue())); + else + rSet.DisableItem( nWhich ); + break; + } + case SID_ATTR_PARA_LEFT_TO_RIGHT: + case SID_ATTR_PARA_RIGHT_TO_LEFT: + { + if ( !SvtLanguageOptions().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 : + { + SvtCTLOptions aCTLOptions; + bool bEnabled = aCTLOptions.IsCTLFontEnabled(); + 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) +{ + rView.ExecSearch(rReq); +} + +void SwAnnotationShell::StateSearch(SfxItemSet &rSet) +{ + rView.StateSearch(rSet); +} + +void SwAnnotationShell::ExecClpbrd(SfxRequest const &rReq) +{ + SwPostItMgr* pPostItMgr = rView.GetPostItMgr(); + if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() ) + return; + + OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView(); + + 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 pDlg(pFact->CreatePasteDialog(rView.GetEditWin().GetFrameWeld())); + + pDlg->Insert( SotClipboardFormatId::STRING, OUString() ); + pDlg->Insert( SotClipboardFormatId::RTF, OUString() ); + pDlg->Insert( SotClipboardFormatId::RICHTEXT, OUString() ); + + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( &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(pItem)) + nFormat = static_cast(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 = rView.GetPostItMgr(); + if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() ) + return; + OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView(); + + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( &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 = 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(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(255, sSel.getLength())); + aHLinkItem.SetName(comphelper::string::stripEnd(sSel, ' ')); + } + + sal_uInt16 nHtmlMode = ::GetHtmlMode(rView.GetDocShell()); + aHLinkItem.SetInsertMode(static_cast(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 = rView.GetPostItMgr(); + if ( !pPostItMgr ) + return; + + sal_uInt16 nSlot = rReq.GetSlot(); + switch (nSlot) + { + case FN_REPLY: + case FN_POSTIT: + case FN_DELETE_COMMENT: + case FN_RESOLVE_NOTE: + if ( pPostItMgr->HasActiveSidebarWin() ) + pPostItMgr->GetActiveSidebarWin()->ExecuteCommand(nSlot); + break; + case FN_DELETE_ALL_NOTES: + pPostItMgr->Delete(); + break; + case FN_FORMAT_ALL_NOTES: + pPostItMgr->ExecuteFormatAllDialog(rView); + break; + case FN_DELETE_NOTE_AUTHOR: + { + const SfxStringItem* pItem = rReq.GetArg(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(nSlot); + if ( pItem ) + pPostItMgr->Hide( pItem->GetValue() ); + else if ( pPostItMgr->HasActiveSidebarWin() ) + pPostItMgr->Hide( pPostItMgr->GetActiveSidebarWin()->GetAuthor() ); + } + } +} + +void SwAnnotationShell::GetNoteState(SfxItemSet &rSet) +{ + SwPostItMgr* pPostItMgr = 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: + { + 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_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()->IsProtected()) && + ( (nSlotId==FN_DELETE_COMMENT) || (nSlotId==FN_REPLY) ) ) + rSet.DisableItem( nWhich ); + } + nWhich = aIter.NextWhich(); + } +} + +void SwAnnotationShell::ExecLingu(SfxRequest &rReq) +{ + SwPostItMgr* pPostItMgr = rView.GetPostItMgr(); + if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() ) + return; + + OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView(); + sal_uInt16 nSlot = rReq.GetSlot(); + SwWrtShell &rSh = 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,rView,rSh); + break; + } + case SID_THES: + { + OUString aReplaceText; + const SfxStringItem* pItem2 = rReq.GetArg(SID_THES); + if (pItem2) + aReplaceText = pItem2->GetValue(); + if (!aReplaceText.isEmpty()) + ReplaceTextWithSynonym( pOLV->GetEditView(), aReplaceText ); + break; + } + case SID_THESAURUS: + { + pOLV->StartThesaurus(); + break; + } + case SID_HANGUL_HANJA_CONVERSION: + pOLV->StartTextConversion( 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 aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", uno::Any(Reference())} + })); + 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( 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 = 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: + { + const SfxPoolItem &rItem = rView.GetWrtShell().GetDoc()->GetDefault( + GetWhichOfScript( RES_CHRATR_LANGUAGE, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage())) ); + LanguageType nLang = static_cast( + 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()) + { + rView.GetViewFrame()->GetBindings().SetVisibleState( nWhich, false ); + rSet.DisableItem(nWhich); + } + else + 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 = 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 ) + { + SwPostItMgr* pPostItMgr = 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 = rView.GetWrtShell(); + SwUndoId nUndoId(SwUndoId::EMPTY); + + long aOldHeight = rView.GetPostItMgr()->HasActiveSidebarWin() + ? rView.GetPostItMgr()->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(pItem)->GetValue(); + switch( nId ) + { + case SID_UNDO: + { + rSh.GetLastUndoInfo(nullptr, &nUndoId); + if (nUndoId == SwUndoId::CONFLICT) + { + rReq.SetReturnValue( SfxUInt32Item(nId, static_cast(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(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; + } + } + + rView.GetViewFrame()->GetBindings().InvalidateAll(false); + + if (rView.GetPostItMgr()->HasActiveSidebarWin()) + rView.GetPostItMgr()->GetActiveSidebarWin()->ResizeIfNecessary(aOldHeight,rView.GetPostItMgr()->GetActiveSidebarWin()->GetPostItTextHeight()); +} + +void SwAnnotationShell::StateUndo(SfxItemSet &rSet) +{ + SwPostItMgr* pPostItMgr = rView.GetPostItMgr(); + if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() ) + return; + + SfxWhichIter aIter(rSet); + SwUndoId nUndoId(SwUndoId::EMPTY); + sal_uInt16 nWhich = aIter.FirstWhich(); + SfxUndoManager* pUndoManager = GetUndoManager(); + SfxViewFrame *pSfxViewFrame = rView.GetViewFrame(); + SwWrtShell &rSh = rView.GetWrtShell(); + + while( nWhich ) + { + switch ( nWhich ) + { + case SID_UNDO: + { + sal_uInt16 nCount = pUndoManager ? pUndoManager->GetUndoActionCount() : 0; + if ( nCount ) + pSfxViewFrame->GetSlotState( nWhich, pSfxViewFrame->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(SID_REPAIRPACKAGE)) ); + } + else + rSet.DisableItem(nWhich); + break; + } + case SID_REDO: + { + sal_uInt16 nCount = pUndoManager ? pUndoManager->GetRedoActionCount() : 0; + if ( nCount ) + pSfxViewFrame->GetSlotState( nWhich, pSfxViewFrame->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(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 ) ).append("\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: + { + pSfxViewFrame->GetSlotState( nWhich, pSfxViewFrame->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 = rView.GetPostItMgr(); + if ( !pPostItMgr || !pPostItMgr->HasActiveSidebarWin() ) + return; + + OutlinerView* pOLV = pPostItMgr->GetActiveSidebarWin()->GetOutlinerView(); + + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = nullptr; + if( pArgs ) + pArgs->GetItemState(GetPool().GetWhich(SID_CHARMAP), false, &pItem); + + OUString sSym; + OUString sFontName; + if ( pItem ) + { + sSym = static_cast(pItem)->GetValue(); + const SfxPoolItem* pFtItem = nullptr; + pArgs->GetItemState( GetPool().GetWhich(SID_ATTR_SPECIALCHAR), false, &pFtItem); + + if (const SfxStringItem* pFontItem = dynamic_cast(pFtItem)) + sFontName = pFontItem->GetValue(); + } + + SfxItemSet aSet(pOLV->GetAttribs()); + SvtScriptType nScript = pOLV->GetSelectedScriptType(); + std::shared_ptr aSetDlgFont(std::make_shared(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(pI->Clone())); + } + else + { + aSetDlgFont.reset(static_cast(aSet.Get( GetWhichOfScript( + SID_ATTR_CHAR_FONT, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) )).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(*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 = rView.GetViewFrame()->GetFrame().GetFrameInterface(); + ScopedVclPtr pDlg(pFact->CreateCharMapDialog(rView.GetFrameWeld(), aAllSet, xFrame)); + pDlg->Execute(); + return; + } + + // do not flicker + pOLV->HideCursor(); + Outliner * pOutliner = pOLV->GetOutliner(); + pOutliner->SetUpdateMode(false); + + SfxItemSet aOldSet( pOLV->GetAttribs() ); + SfxItemSet aFontSet( + *aOldSet.GetPool(), + svl::Items< + EE_CHAR_FONTINFO, EE_CHAR_FONTINFO, + EE_CHAR_FONTINFO_CJK, EE_CHAR_FONTINFO_CTL>{}); + 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->SetUpdateMode(true); + pOLV->ShowCursor(); + + rReq.AppendItem( SfxStringItem( GetPool().GetWhich(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 000000000..44d78d6e5 --- /dev/null +++ b/sw/source/uibase/shells/basesh.cxx @@ -0,0 +1,3039 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +FlyMode SwBaseShell::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 +#include + +#include +#include + +namespace +{ + SvxContourDlg* GetContourDlg(SwView const &rView) + { + SfxChildWindow *pWnd = rView.GetViewFrame()->GetChildWindow(SvxContourDlgChildWindow::GetChildWindowId()); + return pWnd ? static_cast(pWnd->GetController().get()) : nullptr; + } + + SvxIMapDlg* GetIMapDlg(SwView const &rView) + { + SfxChildWindow* pWnd = rView.GetViewFrame()->GetChildWindow(SvxIMapDlgChildWindow::GetChildWindowId()); + return pWnd ? static_cast(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()); +} + + +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; + std::unique_ptr pList(new TargetList); + SfxFrame::GetDefaultTargetList(*pList); + + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + rSh.GetFlyFrameAttr( aSet ); + const SwFormatURL &rURL = aSet.Get( RES_URL ); + SvxIMapDlgChildWindow::UpdateIMapDlg( + aGrf, rURL.GetMap(), pList.get(), 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: + rSh.DelRight(); + break; + + case FN_BACKSPACE: + + if( rSh.IsNoNum() ) + { + rSh.SttCursorMove(); + bool bLeft = rSh.Left( CRSR_SKIP_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: + rView.GetEditWin().FlushInBuffer(); + if ( rSh.HasSelection() ) + { + rtl::Reference 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 = &rView; + + RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA; + const SfxUInt16Item* pAnchorType = rReq.GetArg(FN_PARAM_1); + if (pAnchorType) + nAnchorType = static_cast(pAnchorType->GetValue()); + bool bIgnoreComments = false; + const SfxBoolItem* pIgnoreComments = rReq.GetArg(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); + } + 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 = &rView; + + SwTransferable::PasteFormat( rSh, aDataHelper, + static_cast(static_cast(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); + } + } + } + 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 = &rView; + rReq.Ignore(); + bIgnore = true; + if(SwTransferable::PasteUnformatted( rSh, aDataHelper )) + { + SfxViewFrame* pViewFrame = pView->GetViewFrame(); + uno::Reference< frame::XDispatchRecorder > xRecorder = + pViewFrame->GetBindings().GetRecorder(); + if(xRecorder.is()) { + SfxRequest aReq( pViewFrame, SID_CLIPBOARD_FORMAT_ITEMS ); + aReq.AppendItem( SfxUInt32Item( SID_CLIPBOARD_FORMAT_ITEMS, static_cast(SotClipboardFormatId::STRING) ) ); + aReq.Done(); + } + } + + if (rSh.IsFrameSelected() || rSh.IsObjSelected()) + rSh.EnterSelFrameMode(); + pView->AttrChangedNotify(nullptr); + } + else + return; + } + break; + + case SID_PASTE_SPECIAL: + { + std::shared_ptr aDataHelper = + std::make_shared(TransferableDataHelper::CreateFromSystemClipboard( &rSh.GetView().GetEditWin())); + + if( aDataHelper->GetXTransferable().is() + && SwTransferable::IsPaste( rSh, *aDataHelper ) + && !rSh.CursorInsideInputField() ) + { + rReq.Ignore(); + bIgnore = true; + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + VclPtr 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 = &rView; + bool bRet = false; + SotClipboardFormatId nFormatId = pDlg->GetFormatOnly(); + + if( nFormatId != SotClipboardFormatId::NONE ) + bRet = SwTransferable::PasteFormat( rSh, *aDataHelper, nFormatId ); + + if (bRet) + { + SfxViewFrame* pViewFrame = pView->GetViewFrame(); + uno::Reference< frame::XDispatchRecorder > xRecorder = + pViewFrame->GetBindings().GetRecorder(); + if(xRecorder.is()) { + SfxRequest aReq( pViewFrame, SID_CLIPBOARD_FORMAT_ITEMS ); + aReq.AppendItem( SfxUInt32Item( SID_CLIPBOARD_FORMAT_ITEMS, static_cast(nFormatId) ) ); + aReq.Done(); + } + } + + if (rSh.IsFrameSelected() || rSh.IsObjSelected()) + rSh.EnterSelFrameMode(); + pView->AttrChangedNotify(nullptr); + } + + 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( nWhich ); + SwTransferable::FillClipFormatItem( rSh, aDataHelper, aFormatItem ); + rSet.Put( aFormatItem ); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + +// Perform undo + +void SwBaseShell::ExecUndo(SfxRequest &rReq) +{ + 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(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; + if (pArgs && pArgs->GetItemState(SID_REPAIRPACKAGE, false, &pItem) == SfxItemState::SET) + bRepair = static_cast(pItem)->GetValue(); + + // #i106349#: save pointer: undo/redo may delete the shell, i.e., this! + SfxViewFrame *const pViewFrame( 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(); + rWrtShell.Do( SwWrtShell::UNDO, nCnt ); + for (SwViewShell& rShell : rWrtShell.GetRingContainer()) + rShell.UnlockPaint(); + } + break; + + case SID_REDO: + if (rUndoRedo.GetFirstRedoInfo(nullptr, &nUndoId, &rWrtShell.GetView())) + { + for (SwViewShell& rShell : rWrtShell.GetRingContainer()) + rShell.LockPaint(); + 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(SID_REPAIRPACKAGE)) ); + } + else if (nUndoId == SwUndoId::INSFMTATTR) + { + rWrtShell.GetDoc()->GetDocShell()->GetStyleSheetPool()->Broadcast(SfxHint(SfxHintId::StyleSheetModified)); + } + + if (pViewFrame) { pViewFrame->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(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(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(); + } +} + +// 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::getUnoTunnelImplementation(xModel); + pDoc->NotifyRefreshListeners(); + rSh.CalcLayout(); + } + break; + case FN_UPDATE_FIELDS: + { + 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_CHARTS: + { + SwWait aWait( *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.CalcLayout(); + } + 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); + 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(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( *rView.GetDocShell(), true ); + + OUString aGrfName, aFltName; + const Graphic aGrf( pGalleryItem->GetGraphic() ); + + if ( nSelType & SelectionType::Graphic ) + rSh.ReRead( aGrfName, aFltName, &aGrf ); + else + rSh.Insert( 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(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 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 = + static_cast(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 pDlg(pFact->CreateSwConvertTableDlg(GetView(), bToTable)); + if( RET_OK == pDlg->Execute() ) + { + pDlg->GetValues( cDelim, aInsTableOpts, pTAFormat ); + + } + } + + if( cDelim ) + { + //Shell change! + SwView& rSaveView = rView; + bool bInserted = false; + //recording: + SfxViewFrame* pViewFrame = GetView().GetViewFrame(); + if( SfxRequest::HasMacroRecorder(pViewFrame) ) + { + SfxRequest aReq( pViewFrame, 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(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* pVFrame = GetView().GetViewFrame(); + pVFrame->ToggleChildWindow( nId ); + pVFrame->GetBindings().Invalidate( SID_IMAP ); + + if ( pVFrame->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() ) + { + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + rSh.GetFlyFrameAttr( aSet ); + SwFormatURL aURL( aSet.Get( RES_URL ) ); + aURL.SetMap( &pDlg->GetImageMap() ); + aSet.Put( aURL ); + rSh.SetFlyFrameAttr( aSet ); + } + } + break; + case SID_CONTOUR_DLG: + { + sal_uInt16 nId = SvxContourDlgChildWindow::GetChildWindowId(); + + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + pVFrame->ToggleChildWindow( nId ); + pVFrame->GetBindings().Invalidate( SID_CONTOUR_DLG ); + + SelectionType nSel = rSh.GetSelectionType(); + if ( pVFrame->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(); + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{}); + 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, rSh.GetPhyPageNum()); + 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 ) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + 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(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) + switch(nSlot) + { + case SID_ATTR_BRUSH: + case SID_ATTR_BORDER_SHADOW: + case RES_SHADOW: + { + rSh.StartAllAction(); + // Tabele 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: + { + // Tabele 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 && + !aGrfUpdateSlots.empty() ) + { + bool bProtect = FlyProtectFlags::NONE != rSh.IsSelObjProtected(FlyProtectFlags::Content|FlyProtectFlags::Parent); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + for( const auto nSlot : aGrfUpdateSlots ) + { + bool bSetState = false; + bool bState = false; + switch( nSlot ) + { + case SID_IMAP: + case SID_IMAP_EXEC: + { + sal_uInt16 nId = SvxIMapDlgChildWindow::GetChildWindowId(); + SfxChildWindow *pChildWindow = pVFrame->HasChildWindow(nId) ? + pVFrame->GetChildWindow(nId) : nullptr; + SvxIMapDlg *pDlg = pChildWindow ? + static_cast(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 = pVFrame->HasChildWindow(nId) ? + pVFrame->GetChildWindow(nId) : nullptr; + SvxIMapDlg *pDlg = pChildWindow ? + static_cast(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 ) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + 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( pGetStateSet ) + pGetStateSet->Put( aBool ); + else + pVFrame->GetBindings().SetState( aBool ); + } + } + aGrfUpdateSlots.clear(); + } +} + +void SwBaseShell::GetState( SfxItemSet &rSet ) +{ + SwWrtShell &rSh = GetShell(); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + 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: + { + SfxItemSet aSet( rSh.GetAttrPool(), + svl::Items{} ); + + // 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(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 = pVFrame->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 && pVFrame->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())) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + 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_PARAGRAPH + || 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())) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + 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 whenn 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_ACCESSIBILITY_CHECK: + { + if (!officecfg::Office::Common::Misc::ExperimentalMode::get()) + rSet.Put(SfxVisibilityItem(nWhich, false)); + } + break; + } + nWhich = aIter.NextWhich(); + } + 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; + + SfxItemSet aSet(GetPool(), svl::Items{}); + 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()); + 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 ) +{ + 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 ), + rView(rVw), + pGetStateSet(nullptr) +{ + SwWrtShell& rWrtSh = rView.GetWrtShell(); + + SetPool(&rWrtSh.GetAttrPool()); + SetName("Base"); + rWrtSh.SetGrfArrivedLnk( LINK( this, SwBaseShell, GraphicArrivedHdl)); +} + +SwBaseShell::~SwBaseShell() +{ + if( rView.GetCurShell() == this ) + rView.ResetSubShell(); + + Link aTmp( LINK( this, SwBaseShell, GraphicArrivedHdl)); + if( aTmp == rView.GetWrtShell().GetGrfArrivedLnk() ) + rView.GetWrtShell().SetGrfArrivedLnk( Link() ); +} + +void SwBaseShell::ExecTextCtrl( SfxRequest& rReq ) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + + if( pArgs) + { + SwWrtShell &rSh = GetShell(); + std::unique_ptr pSSetItem; + sal_uInt16 nSlot = rReq.GetSlot(); + SfxItemPool& rPool = rSh.GetAttrPool(); + sal_uInt16 nWhich = rPool.GetWhich( nSlot ); + SvtScriptType nScripts = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX; + SfxItemSet aHeightSet( GetPool(), svl::Items{}); + + 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(); + + SfxItemSet aLangSet( GetPool(), svl::Items{}); + 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(nHeight); + break; + case SvtScriptType::ASIAN: + nCTLSize = nHeight* nCTLSize / nCJKSize; + nWesternSize = nHeight * nWesternSize / nCJKSize; + nCJKSize = static_cast(nHeight); + break; + case SvtScriptType::COMPLEX: + nCJKSize = nHeight * nCJKSize / nCTLSize; + nWesternSize = nHeight * nWesternSize / nCTLSize; + nCTLSize = static_cast(nHeight); + break; + default: break; + } + aHeightSet.Put( SvxFontHeightItem( static_cast(nWesternSize), 100, RES_CHRATR_FONTSIZE )); + aHeightSet.Put( SvxFontHeightItem( static_cast(nCJKSize), 100, RES_CHRATR_CJK_FONTSIZE )); + aHeightSet.Put( SvxFontHeightItem( static_cast(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->IsAutoUpdateFormat() ) + { + rSh.AutoUpdatePara( pColl, *pArgs ); + bAuto = true; + } + } + + if (!bAuto) + { + rSh.SetAttrSet( *pArgs ); + } + } + } + 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::unique_ptr 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.reset(new SfxItemSet( *rSet.GetPool(), + svl::Items{} )); + 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(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(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 aBrushItem(std::make_unique(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 + SfxItemSet aCoreSet(GetPool(), svl::Items{}); + + 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(), 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 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 aBrushItem(std::make_unique(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 + SfxItemSet aCoreSet(GetPool(), svl::Items{}); + + 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: + { + const SfxPoolItem* pColorStringItem = nullptr; + bool bIsTransparent = false; + + aBrushItem->SetGraphicPos(GPOS_NONE); + + sal_uInt16 nSlotId = (nSlot == SID_BACKGROUND_COLOR) ? SID_BACKGROUND_COLOR : SID_TABLE_CELL_BACKGROUND_COLOR; + if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_COLOR_STR, false, &pColorStringItem)) + { + OUString sColor = static_cast(pColorStringItem)->GetValue(); + if (sColor == "transparent") + { + bIsTransparent = true; + } + else + { + Color aColor(sColor.toInt32(16)); + + aBrushItem->SetColor(aColor); + + SvxColorItem aNewColorItem(nSlotId); + aNewColorItem.SetValue(aColor); + + GetView().GetViewFrame()->GetBindings().SetState(aNewColorItem); + } + } + else if (pArgs) + { + const SvxColorItem& rNewColorItem = static_cast(pArgs->Get(nSlotId)); + const Color& rNewColor = rNewColorItem.GetValue(); + aBrushItem->SetColor(rNewColor); + 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(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 + SfxItemSet aCoreSet(GetPool(), svl::Items{}); + + 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->IsAutoUpdateFormat()) + { + rSh.AutoUpdateFrame(pFormat, aCoreSet); + } + else + { + rSh.SetFlyFrameAttr(aCoreSet); + } + } + else + { + SwTextFormatColl* pColl = rSh.GetCurTextFormatColl(); + + if(pColl && pColl->IsAutoUpdateFormat()) + { + rSh.AutoUpdatePara(pColl, aCoreSet); + } + else + { + rSh.SetAttrSet(aCoreSet); + } + } + } + + rReq.Done(); +} + +void SwBaseShell::GetBorderState(SfxItemSet &rSet) +{ + SwWrtShell &rSh = GetShell(); + // Tabele cell(s) selected? + bool bPrepare = true; + bool bTableMode = rSh.IsTableMode(); + if ( bTableMode ) + { + SfxItemSet aCoreSet( GetPool(), + svl::Items{} ); + 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 pDlg(pFact->CreateTitlePageDlg(pMDI)); + pDlg->Execute(); + } + break; + case FN_FORMAT_PAGE_DLG: + case FN_FORMAT_PAGE_COLUMN_DLG: + case FN_FORMAT_PAGE_SETTING_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(); + + OString 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_DLG: + if (pItem) + sPageId = OUStringToOString(static_cast(pItem)->GetValue(), RTL_TEXTENCODING_UTF8); + break; + } + rTempView.GetDocShell()->FormatPage(rPageDesc.GetName(), sPageId, rSh, &rReq); + rTempView.InvalidateRulerPos(); + + bDone = true; // FormatPage() takes care of calling Done() + } + } + break; + case FN_FORMAT_BORDER_DLG: + { + SfxItemSet aSet( rSh.GetAttrPool(), + svl::Items{} ); + ScopedVclPtr 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: + { + SfxItemSet aSet( rSh.GetAttrPool(), + svl::Items{} ); + + ScopedVclPtr pDlg; + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + + // Table cell(s) selected? + if ( rSh.IsTableMode() ) + { + // Get background attributes of the table and put it in the set + std::unique_ptr aBrush; + rSh.GetBoxBackground( aBrush ); + pDlg.disposeAndReset(pFact->CreateSwBackgroundDialog(pMDI, aSet)); + aSet.Put( *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(*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_ACCESSIBILITY_CHECK: + { + sw::AccessibilityCheck aCheck(rSh.GetDoc()); + aCheck.check(); + svx::AccessibilityCheckDialog aDialog(pMDI, aCheck.getIssueCollecton()); + aDialog.run(); + } + break; + default:OSL_FAIL("wrong Dispatcher (basesh.cxx)"); + } + if(!bDone) + rReq.Done(); +} + +SwWrtShell& SwBaseShell::GetShell() +{ + return rView.GetWrtShell(); +} + +SwWrtShell* SwBaseShell::GetShellPtr() +{ + return 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& 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()->SetName( aTableName ); + + if( pTAFormat != nullptr && !aAutoName.isEmpty() + && aAutoName != SwViewShell::GetShellRes()->aStrNone ) + { + SwTableNode* pTableNode = const_cast( rSh.IsCursorInTable() ); + if ( pTableNode ) + { + pTableNode->GetTable().SetTableStyleName( aAutoName ); + SwUndoTableAutoFormat* pUndo = new SwUndoTableAutoFormat( *pTableNode, *pTAFormat ); + if ( pUndo ) + rSh.GetIDocumentUndoRedo().AppendUndo( std::unique_ptr(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 ) ) + { + 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 pTAFormatIn; + + if( pArgs && pArgs->Count() >= 2 ) + { + const SfxStringItem* pName = _rRequest.GetArg(FN_INSERT_TABLE); + const SfxUInt16Item* pCols = _rRequest.GetArg(SID_ATTR_TABLE_COLUMN); + const SfxUInt16Item* pRows = _rRequest.GetArg(SID_ATTR_TABLE_ROW); + const SfxInt32Item* pFlags = _rRequest.GetArg(FN_PARAM_1); + const SfxStringItem* pAuto = _rRequest.GetArg(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(pFlags->GetValue()); + else + { + const SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + aInsTableOptsIn = pModOpt->GetInsTableFlags(bHTMLMode); + } + } + + if( !nColsIn || !nRowsIn ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + std::shared_ptr pAbstractDialog(pFact->CreateInsTableDlg(rTempView)); + std::shared_ptr 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 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(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 &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(SID_GALLERY_BG_POS); + const SvxBrushItem* pBrush = rReq.GetArg(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 ) + { + SfxItemSet aCoreSet(GetPool(), svl::Items{}); + 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 + case FN_CHANGE_DBFIELD: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwChangeDBDlg(GetView())); + pDlg->Execute(); + } + break; +#endif + default: + OSL_FAIL("wrong dispatcher"); + } +} + +/* 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 000000000..4764deced --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#define ShellClass_SwBezierShell +#include +#include + +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); + + 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( 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 000000000..36d231bc4 --- /dev/null +++ b/sw/source/uibase/shells/drawdlg.cxx @@ -0,0 +1,373 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star::drawing; + +void SwDrawShell::ExecDrawDlg(SfxRequest& rReq) +{ + SwWrtShell* pSh = &GetShell(); + SdrView* pView = pSh->GetDrawView(); + SdrModel* pDoc = pView->GetModel(); + bool bChanged = pDoc->IsChanged(); + pDoc->SetChanged(false); + + SfxItemSet aNewAttr( pDoc->GetItemPool() ); + pView->GetAttributes( aNewAttr ); + + GetView().NoRotate(); + + switch (rReq.GetSlot()) + { + case FN_DRAWTEXT_ATTR_DLG: + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr 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()); + rReq.Done(*(pDlg->GetOutputItemSet())); + pSh->EndAction(); + } + } + } + break; + + case SID_MEASURE_DLG: + { + bool bHasMarked = pView->AreObjectsMarked(); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr 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 pDlg(pFact->CreateSvxAreaTabDialog(rReq.GetFrameWeld(), + &aNewAttr, + pDoc, + true)); + + pDlg->StartExecuteAsync([bChanged, bHasMarked, pDoc, pDlg, pSh, pView, this]( + sal_Int32 nResult){ + 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 (pDoc->IsChanged()) + GetShell().SetModified(); + else if (bChanged) + pDoc->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 pDlg(pFact->CreateSvxLineTabDialog(rReq.GetFrameWeld(), + &aNewAttr, + pDoc, + pObj, + bHasMarked)); + + pDlg->StartExecuteAsync([bChanged, bHasMarked, pDoc, pDlg, pSh, pView, this]( + sal_Int32 nResult){ + 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 (pDoc->IsChanged()) + GetShell().SetModified(); + else if (bChanged) + pDoc->SetChanged(); + + pDlg->disposeOnce(); + }); + } + break; + + default: + break; + } + + if (pDoc->IsChanged()) + GetShell().SetModified(); + else + if (bChanged) + pDoc->SetChanged(); +} + +namespace +{ + void lcl_convertStringArguments(sal_uInt16 nSlot, std::unique_ptr& pArgs) + { + Color aColor; + OUString sColor; + const SfxPoolItem* pItem = nullptr; + + if (SfxItemState::SET == pArgs->GetItemState(SID_ATTR_COLOR_STR, false, &pItem)) + { + sColor = static_cast(pItem)->GetValue(); + + if (sColor == "transparent") + aColor = COL_TRANSPARENT; + else + aColor = Color(sColor.toInt32(16)); + + switch (nSlot) + { + case SID_ATTR_LINE_COLOR: + { + XLineColorItem aLineColorItem(OUString(), aColor); + pArgs->Put(aLineColorItem); + break; + } + + case SID_ATTR_FILL_COLOR: + { + XFillColorItem aFillColorItem(OUString(), aColor); + pArgs->Put(aFillColorItem); + break; + } + } + } + else if (SfxItemState::SET == pArgs->GetItemState(SID_ATTR_LINE_WIDTH_ARG, false, &pItem)) + { + double fValue = static_cast(pItem)->GetValue(); + // FIXME: different units... + int nPow = 100; + int nValue = fValue * nPow; + + XLineWidthItem aItem(nValue); + pArgs->Put(aItem); + } + if (SfxItemState::SET == pArgs->GetItemState(SID_FILL_GRADIENT_JSON, false, &pItem)) + { + const SfxStringItem* pJSON = static_cast(pItem); + if (pJSON) + { + XGradient aGradient = XGradient::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 pNewArgs = pArgs->Clone(); + lcl_convertStringArguments(rReq.GetSlot(), 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(SfxItemSet& rSet) +{ + // Transparent fill options are None, Solid, Linear, Axial, Radial, Elliptical, Quadratic, Square. + // 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 + (rSet.GetItem(XATTR_FILLFLOATTRANSPARENCE)); + if (!pFillFloatTranspItem || pFillFloatTranspItem->IsEnabled()) + return; + + const XFillTransparenceItem* pFillTranspItem = + rSet.GetItem(XATTR_FILLTRANSPARENCE); + + if (!pFillTranspItem) + return; + + XGradient aTmpGradient = pFillFloatTranspItem->GetGradientValue(); + sal_uInt16 nTranspPercent = pFillTranspItem->GetValue(); + // Encode transparency percentage as intensity + sal_uInt16 nIntensity = 100 - std::min + (std::max(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 ) + { + pSdrView->GetAttributes( rSet ); + 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 000000000..958a38b2a --- /dev/null +++ b/sw/source/uibase/shells/drawsh.cxx @@ -0,0 +1,603 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ShellClass_SwDrawShell +#include +#include + +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) + { + SvxOpenGraphicDialog aDlg(SwResId(STR_INSERT_GRAPHIC), GetView().GetFrameWeld()); + + if (ERRCODE_NONE == aDlg.Execute()) + { + Graphic aGraphic; + ErrCode nError = aDlg.GetGraphic(aGraphic); + + if(ERRCODE_NONE == nError) + { + const bool bAsLink(aDlg.IsAsLink()); + SdrObject* pResult = &rObject; + + rSh.StartUndo(SwUndoId::PASTE_CLIPBOARD); + + if (SdrGrafObj* pSdrGrafObj = dynamic_cast(&rObject)) + { + SdrGrafObj* pNewGrafObj(pSdrGrafObj->CloneSdrObject(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); + + OUString aReferer; + SwDocShell *pDocShell = rSh.GetDoc()->GetDocShell(); + if (pDocShell->HasName()) { + aReferer = pDocShell->GetMedium()->GetName(); + } + + // set in all cases - the Clone() will have copied an existing link (!) + pNewGrafObj->SetGraphicLink( + bAsLink ? aDlg.GetPath() : OUString(), + aReferer, + bAsLink ? aDlg.GetDetectedFilter() : OUString()); + + pResult = pNewGrafObj; + } + else // if(rObject.IsClosedObj() && !dynamic_cast< SdrOle2Obj* >(&rObject)) + { + pSdrView->AddUndo(std::make_unique(rObject)); + + SfxItemSet aSet(pSdrView->GetModel()->GetItemPool(), svl::Items{}); + + aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP)); + aSet.Put(XFillBitmapItem(OUString(), 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_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( &rSh.GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) ); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + if (pArgs) + { + pVFrame->SetChildWindow(SvxFontWorkChildWindow::GetChildWindowId(), + static_cast((pArgs->Get(SID_FONTWORK))).GetValue()); + } + else + pVFrame->ToggleChildWindow( SvxFontWorkChildWindow::GetChildWindowId() ); + pVFrame->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); + } + break; + } + case FN_REMOVE_TEXT_BOX: + { + if (SdrObject* pObj = IsSingleFillableNonOLESelected()) + { + SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj); + if (pFrameFormat) + SwTextBoxHelper::destroy(pFrameFormat); + } + 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)) + { + if (SdrObjCustomShape* pCustomShape = dynamic_cast( 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().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)) + 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"); + + SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Draw)); +} + +// 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 = dynamic_cast< const SdrTextObj* >(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 000000000..2e2f5fd52 --- /dev/null +++ b/sw/source/uibase/shells/drformsh.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ShellClass_SwDrawFormShell +#include +#include + +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(pItem); + bool bConvertToText = rHLinkItem.GetInsertMode() == HLINK_DEFAULT || + rHLinkItem.GetInsertMode() == HLINK_FIELD; + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + if (rMarkList.GetMark(0)) + { + SdrUnoObj* pUnoCtrl = dynamic_cast( 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( 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(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 000000000..c707b8037 --- /dev/null +++ b/sw/source/uibase/shells/drwbassh.cxx @@ -0,0 +1,1042 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define ShellClass_SwDrawBaseShell +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +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( OBJ_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 ) + { + SfxItemSet aSet( + GetPool(), + svl::Items< + 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.Put(SfxBoolItem(SID_HTML_MODE, + 0 != ::GetHtmlMode(pSh->GetView().GetDocShell()))); + + aSet.Put(SfxInt16Item(FN_DRAW_WRAP_DLG, sal_uInt8(pSh->GetLayerId()))); + + pSh->GetObjAttr(aSet); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwWrapDlg(GetView().GetFrameWeld(), aSet, pSh)); + + if (pDlg->Execute() == RET_OK) + { + const SfxPoolItem* pWrapItem; + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + if(SfxItemState::SET == pOutSet->GetItemState(FN_DRAW_WRAP_DLG, false, &pWrapItem)) + { + short nLayer = static_cast(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 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() == OBJ_CAPTION ) + bCaption = true; + + if (bCaption) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + VclPtr pCaptionDlg = + pFact->CreateCaptionDialog( rReq.GetFrameWeld(), pSdrView, nAllowedAnchors ); + pDlg.reset(pCaptionDlg); + pCaptionDlg->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) ); + } + else + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + VclPtr pTransform = + pFact->CreateSvxTransformTabDialog(rReq.GetFrameWeld(), nullptr, pSdrView, nAllowedAnchors); + pDlg.reset(pTransform); + pTransform->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) ); + } + SfxItemSet aNewAttr(pSdrView->GetGeoAttrFromMarked()); + + const sal_uInt16* pRange = pDlg->GetInputRanges( *aNewAttr.GetPool() ); + SfxItemSet aSet( *aNewAttr.GetPool(), pRange ); + FieldUnit eMetric = ::GetDfltMetric( dynamic_cast(&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(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){ + 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 ); + + SfxItemSet aFrameAttrSet(GetPool(), svl::Items{}); + + bool bSingleSelection = rMarkList.GetMarkCount() == 1; + + const SfxPoolItem* pAnchorItem; + if(SfxItemState::SET == pOutSet->GetItemState( + SID_ATTR_TRANSFORM_ANCHOR, false, &pAnchorItem)) + { + if(!bSingleSelection) + pSh->ChgAnchor(static_cast(static_cast(pAnchorItem) + ->GetValue()), false, bPosCorr ); + else + { + SwFormatAnchor aAnchor(pFrameFormat->GetAnchor()); + aAnchor.SetType(static_cast(static_cast(pAnchorItem)->GetValue())); + aFrameAttrSet.Put( aAnchor ); + } + } + const SfxPoolItem* pHoriOrient = nullptr; + const SfxPoolItem* pHoriRelation = nullptr; + const SfxPoolItem* pHoriPosition = nullptr; + const SfxPoolItem* pHoriMirror = nullptr; + pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_ORIENT, false, &pHoriOrient); + pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_RELATION, false, &pHoriRelation); + pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_POSITION, false, &pHoriPosition); + pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_MIRROR, false, &pHoriMirror); + if(pHoriOrient || pHoriRelation || pHoriPosition || pHoriMirror) + { + if(pHoriOrient) + aHOrientFinal.SetHoriOrient( + static_cast(pHoriOrient)->GetValue()); + if(pHoriRelation) + aHOrientFinal.SetRelationOrient( + static_cast(pHoriRelation)->GetValue()); + if(pHoriPosition) + aHOrientFinal.SetPos( static_cast(pHoriPosition)->GetValue()); + if(pHoriMirror) + aHOrientFinal.SetPosToggle( static_cast(pHoriMirror)->GetValue()); + aFrameAttrSet.Put(aHOrientFinal); + } + + const SfxPoolItem* pVertOrient = nullptr; + const SfxPoolItem* pVertRelation = nullptr; + const SfxPoolItem* pVertPosition = nullptr; + pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_ORIENT, false, &pVertOrient); + pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_RELATION, false, &pVertRelation); + pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_POSITION, false, &pVertPosition); + if(pVertOrient || pVertRelation || pVertPosition ) + { + if(pVertOrient) + aVOrientFinal.SetVertOrient( + static_cast(pVertOrient)->GetValue()); + if(pVertRelation) + aVOrientFinal.SetRelationOrient( + static_cast(pVertRelation)->GetValue()); + if(pVertPosition) + aVOrientFinal.SetPos( static_cast(pVertPosition)->GetValue()); + aFrameAttrSet.Put( aVOrientFinal ); + } + const SfxPoolItem* pFollowItem = nullptr; + pOutSet->GetItemState(RES_FOLLOW_TEXT_FLOW, false, &pFollowItem); + 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; + + 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 + } + } + break; + + case SID_GROUP: + if (pSh->IsObjSelected() > 1 && pSh->IsGroupAllowed()) + { + pSh->GroupSelection(); + rBind.Invalidate(SID_UNGROUP); + } + break; + + case SID_UNGROUP: + if (pSh->IsGroupSelected() && pSh->IsUnGroupAllowed()) + { + pSh->UnGroupSelection(); + rBind.Invalidate(SID_GROUP); + } + break; + + case SID_ENTER_GROUP: + if (pSh->IsGroupSelected()) + { + 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_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 ) + { + 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); + if (auto pTxFrm = SwTextBoxHelper::getOtherTextBoxFormat(pFrameFormat, RES_DRAWFRMFMT)) + pTxFrm->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); + if (auto pTxFrm = SwTextBoxHelper::getOtherTextBoxFormat(pFrameFormat, RES_DRAWFRMFMT)) + pTxFrm->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 pDlg(pFact->CreateSvxObjectNameDialog(GetView().GetFrameWeld(), aName)); + + pDlg->SetCheckNameHdl(LINK(this, SwDrawBaseShell, CheckGroupShapeNameHdl)); + + if(RET_OK == pDlg->Execute()) + { + pDlg->GetName(aName); + pSelected->SetName(aName); + pSh->SetModified(); + } + } + + 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()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSvxObjectTitleDescDialog(GetView().GetFrameWeld(), + aTitle, aDescription)); + + if(RET_OK == pDlg->Execute()) + { + pDlg->GetTitle(aTitle); + pDlg->GetDescription(aDescription); + + pSelected->SetTitle(aTitle); + pSelected->SetDescription(aDescription); + + pSh->SetModified(); + } + } + + 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() || bProtected || !rSh.IsUnGroupAllowed() ) + rSet.DisableItem( nWhich ); + break; + case SID_ENTER_GROUP: + if ( !rSh.IsGroupSelected() ) + 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); + 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)); + } + } + 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(&GetView())); + + if(!bIsWebView && 1 != pSdrView->GetMarkedObjectCount()) + { + 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(); + sal_uInt16 nObjType = pObj->GetObjIdentifier(); + + if ( nObjType != OBJ_MEASURE ) + bShowMeasure = false; + + // If marked object is 2D, disable format area command. + if ( nObjType == OBJ_PLIN || + nObjType == OBJ_LINE || + nObjType == OBJ_PATHLINE || + nObjType == OBJ_FREELINE || + nObjType == OBJ_EDGE || + nObjType == OBJ_CARC || + 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 SwPosition* pContentPos = nullptr; + SdrView* pSdrView = pSh->GetDrawView(); + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + if( rMarkList.GetMarkCount() == 1 ) + { + SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); + SwFrameFormat* pFrameFormat = FindFrameFormat( pObj ); + pContentPos = pFrameFormat->GetAnchor().GetContentAnchor(); + } + + pSh->CalcBoundRect( aBoundRect, eAnchorType, + rValidation.nHRelOrient, + rValidation.nVRelOrient, + pContentPos, + 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()); + 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 + 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 000000000..185b79dd3 --- /dev/null +++ b/sw/source/uibase/shells/drwtxtex.cxx @@ -0,0 +1,1251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace +{ + void lcl_convertStringArguments(sal_uInt16 nSlot, std::unique_ptr& pArgs) + { + Color aColor; + OUString sColor; + const SfxPoolItem* pItem = nullptr; + + if (SfxItemState::SET == pArgs->GetItemState(SID_ATTR_COLOR_STR, false, &pItem)) + { + sColor = static_cast(pItem)->GetValue(); + + if (sColor == "transparent") + aColor = COL_TRANSPARENT; + else + aColor = Color(sColor.toInt32(16)); + + switch (nSlot) + { + case SID_ATTR_CHAR_COLOR: + { + SvxColorItem aColorItem(aColor, EE_CHAR_COLOR); + pArgs->Put(aColorItem); + break; + } + + case SID_ATTR_CHAR_BACK_COLOR: + { + SvxBackgroundColorItem pBackgroundItem(aColor, EE_CHAR_BKGCOLOR); + pArgs->Put(pBackgroundItem); + break; + } + } + } + } +} + +void SwDrawTextShell::Execute( SfxRequest &rReq ) +{ + SwWrtShell &rSh = GetShell(); + OutlinerView* pOLV = 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 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(SID_THES); + 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(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: + { + SvxLineSpacingItem aLineSpace = static_cast(pNewAttrs->Get( + GetPool().GetWhich(nSlot))); + aLineSpace.SetWhich( EE_PARA_SBL ); + aNewAttr.Put( aLineSpace ); + rReq.Done(); + } + break; + case SID_ATTR_PARA_ULSPACE: + { + SvxULSpaceItem aULSpace = static_cast(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_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(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(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: + case SID_CHAR_DLG_FOR_PARAGRAPH: + { + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxStringItem* pItem = rReq.GetArg(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( pView) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) ); + SfxItemSet aDlgAttr(GetPool(), svl::Items{}); + + // 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 pDlg(pFact->CreateSwCharDlg(pView->GetFrameWeld(), *pView, aDlgAttr, SwCharDlgMode::Draw)); + if (nSlot == SID_CHAR_DLG_EFFECT) + { + pDlg->SetCurPageId("fonteffects"); + } + else if (nSlot == SID_CHAR_DLG_FOR_PARAGRAPH) + { + pDlg->SetCurPageId("font"); + } + else if (pItem) + { + pDlg->SetCurPageId(OUStringToOString(pItem->GetValue(), RTL_TEXTENCODING_UTF8)); + } + + 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( pView) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) ); + SfxItemSet aDlgAttr( + GetPool(), + svl::Items< + EE_ITEMS_START, EE_ITEMS_END, + SID_ATTR_PARA_HYPHENZONE, SID_ATTR_PARA_WIDOWS>{}); + + 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 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 = pSdrView->GetTextEditOutliner(); + EEControlBits nCtrl = pOutliner->GetControlWord(); + + bool bSet = static_cast(rReq.GetArgs()->Get( + nSlot)).GetValue(); + if(bSet) + nCtrl |= EEControlBits::ONLINESPELLING|EEControlBits::ALLOWBIGOBJS; + else + nCtrl &= ~EEControlBits::ONLINESPELLING; + pOutliner->SetControlWord(nCtrl); + + 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(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 SvxFieldData* pField = pOLV->GetFieldAtCursor(); + if (const SvxURLField* pURLField = dynamic_cast(pField)) + { + SfxStringItem aUrl(SID_FILE_NAME, pURLField->GetURL()); + SfxStringItem aTarget(SID_TARGETNAME, pURLField->GetTargetFrame()); + SfxBoolItem aNewView(SID_OPEN_NEW_VIEW, false); + SfxBoolItem aBrowsing(SID_BROWSE, true); + GetView().GetViewFrame()->GetDispatcher()->ExecuteList( + SID_OPENDOC, SfxCallMode::SYNCHRON, { &aUrl, &aTarget, &aNewView, &aBrowsing }); + } + } + break; + + case SID_COPY_HYPERLINK_LOCATION: + { + const SvxFieldData* pField = pOLV->GetFieldAtCursor(); + if (const SvxURLField* pURLField = dynamic_cast(pField)) + { + uno::Reference 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 = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + SdrPageView* pTmpPV = pSdrView->GetSdrPageView(); + SdrView* pTmpView = pSdrView; + + pSdrView->SdrEndTextEdit(true); + + SfxItemSet aAttr( *aNewAttr.GetPool(), + svl::Items{} ); + + 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 = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + SdrPageView* pTmpPV = pSdrView->GetSdrPageView(); + SdrView* pTmpView = pSdrView; + + 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(pPoolItem)->GetValue() ) + bLeftToRight = !bLeftToRight; + } + SfxItemSet aAttr( + *aNewAttr.GetPool(), + svl::Items< + EE_PARA_WRITINGDIR, EE_PARA_WRITINGDIR, + EE_PARA_JUST, EE_PARA_JUST>{}); + + SvxAdjust nAdjust = SvxAdjust::Left; + if( SfxItemState::SET == aEditAttr.GetItemState(EE_PARA_JUST, true, &pPoolItem ) ) + nAdjust = static_cast(pPoolItem)->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 SvxFontListItem* pFontListItem = static_cast< const SvxFontListItem* > + ( SfxObjectShell::Current()->GetItem( SID_ATTR_CHAR_FONTLIST ) ); + 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) + { + lcl_convertStringArguments(nSlot, pNewAttrs); + + aNewAttr.Put(pNewAttrs->Get(nWhich).CloneSetWhich(nEEWhich)); + } + + 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 = pSdrView->GetTextEditOutlinerView(); + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + SfxItemSet aEditAttr(pOLV->GetAttribs()); + const SfxPoolItem *pAdjust = nullptr, *pLSpace = nullptr, *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 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) + aEditAttr.GetItemState(EE_PARA_JUST, false, &pAdjust); + + if (!pAdjust || IsInvalidItem(pAdjust)) + { + rSet.InvalidateItem(nSlotId); + nSlotId = 0; + } + else + bFlag = eAdjust == static_cast(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_15: + nLSpace = 150; + goto ASK_LINESPACE; + case SID_ATTR_PARA_LINESPACE_20: + nLSpace = 200; + goto ASK_LINESPACE; + ASK_LINESPACE: + { + if (!pLSpace) + aEditAttr.GetItemState(EE_PARA_SBL, false, &pLSpace); + + if (!pLSpace || IsInvalidItem(pLSpace)) + { + rSet.InvalidateItem(nSlotId); + nSlotId = 0; + } + else if (nLSpace + == static_cast(pLSpace)->GetPropLineSpace()) + bFlag = true; + else + 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(pEscItem)->GetEscapement()) + bFlag = true; + else + nSlotId = 0; + } + break; + + case SID_THESAURUS: + { + // disable "Thesaurus" if the language is not supported + const SfxPoolItem& rItem = GetShell().GetDoc()->GetDefault(GetWhichOfScript( + RES_CHRATR_LANGUAGE, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage(GetAppLanguage()))); + LanguageType nLang = static_cast(rItem).GetLanguage(); + + uno::Reference 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 (!SvtLanguageOptions().IsVerticalTextEnabled()) + { + rSet.DisableItem(nSlotId); + nSlotId = 0; + } + else + { + SdrOutliner* pOutliner = 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 (!SvtLanguageOptions().IsCTLFontEnabled()) + { + rSet.DisableItem(nWhich); + nSlotId = 0; + } + else + { + SdrOutliner* pOutliner = 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: + { + SvtCJKOptions aCJKOptions; + if (!aCJKOptions.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: + { + SvtCTLOptions aCTLOptions; + bool bEnabled = aCTLOptions.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)) + rSet.DisableItem(nWhich); + } + break; + default: + nSlotId = 0; // don't know this slot + break; + } + + if (nSlotId && bFlag) + rSet.Put(SfxBoolItem(nWhich, bFlag)); + + nWhich = aIter.NextWhich(); + } +} + +void SwDrawTextShell::GetDrawTextCtrlState(SfxItemSet& rSet) +{ + if (!IsTextEdit()) // Otherwise crash! + return; + + OutlinerView* pOLV = 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 SfxPoolItem* pState = rView.GetSlotState(nWhich); + if (pState) + rSet.Put(SfxBoolItem(nWhich, static_cast(pState)->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( 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 = 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 pDlg(pFact->CreatePasteDialog(GetView().GetEditWin().GetFrameWeld())); + + pDlg->Insert(SotClipboardFormatId::STRING, OUString()); + pDlg->Insert(SotClipboardFormatId::RTF, OUString()); + pDlg->Insert(SotClipboardFormatId::RICHTEXT, 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(); + } + + 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(pItem)) + nFormat = static_cast(pUInt32Item->GetValue()); + } + + if (nFormat != SotClipboardFormatId::NONE) + { + if (nFormat == SotClipboardFormatId::STRING) + pOLV->Paste(); + else + pOLV->PasteSpecial(); + } + + break; + } + + default: + OSL_FAIL("wrong dispatcher"); + return; + } +} + +void SwDrawTextShell::StateClpbrd(SfxItemSet &rSet) +{ + if (!IsTextEdit()) // Otherwise crash! + return; + + OutlinerView* pOLV = 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 ); + + 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 ); + + 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 = 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(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(255, sSel.getLength())); + aHLinkItem.SetName(comphelper::string::stripEnd(sSel, ' ')); + } + + sal_uInt16 nHtmlMode = ::GetHtmlMode(GetView().GetDocShell()); + aHLinkItem.SetInsertMode(static_cast(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 000000000..b8d79ebb9 --- /dev/null +++ b/sw/source/uibase/shells/drwtxtsh.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ShellClass_SwDrawTextShell +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(); + pSdrView = rSh.GetDrawView(); + SdrOutliner * pOutliner = pSdrView->GetTextEditOutliner(); + //#97471# mouse click _and_ key input at the same time + if( !pOutliner ) + return ; + OutlinerView* pOLV = 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), + 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 ) + rView.ResetSubShell(); +} + +SwWrtShell& SwDrawTextShell::GetShell() +{ + return 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 = pSdrView->GetTextEditOutlinerView(); + tools::Rectangle aOutRect = pOLV->GetOutputArea(); + + if (tools::Rectangle() != aOutRect) + { + GetShell().GetDrawView()->SetAttributes(rAttr); + } +} + +bool SwDrawTextShell::IsTextEdit() const +{ + return pSdrView->IsTextEdit(); +} + +void SwDrawTextShell::ExecFontWork(SfxRequest const & rReq) +{ + SwWrtShell &rSh = GetShell(); + FieldUnit eMetric = ::GetDfltMetric( dynamic_cast( &rSh.GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) ); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + if ( rReq.GetArgs() ) + { + pVFrame->SetChildWindow(SvxFontWorkChildWindow::GetChildWindowId(), + static_cast( (rReq.GetArgs()-> + Get(SID_FONTWORK))).GetValue()); + } + else + pVFrame->ToggleChildWindow(SvxFontWorkChildWindow::GetChildWindowId()); + + pVFrame->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() ) + { + 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 = dynamic_cast< const SdrTextObj* >(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 = pSdrView->GetTextEditOutlinerView(); + if( rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() ) + { + switch(rReq.GetSlot()) + { + case SID_THESAURUS: + pOutlinerView->StartThesaurus(); + break; + + case SID_HANGUL_HANJA_CONVERSION: + pOutlinerView->StartTextConversion(LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr, + i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true, false); + break; + + case SID_CHINESE_CONVERSION: + { + //open ChineseTranslationDialog + Reference xContext = comphelper::getProcessComponentContext(); + if (!xContext.is()) + return; + + Reference xMCF(xContext->getServiceManager()); + if (!xMCF.is()) + return; + + Reference xDialog( + xMCF->createInstanceWithContext("com.sun.star.linguistic2.ChineseTranslationDialog", xContext), UNO_QUERY); + + Reference xInit(xDialog, UNO_QUERY); + + if (!xInit.is()) + return; + + // initialize dialog + uno::Sequence aSequence(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", uno::Any(Reference())} + })); + 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 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(nSourceLang, nTargetLang, &aTargetFont, nOptions, false, false); + } + + Reference 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(); + pSdrView = rSh.GetDrawView(); + OutlinerView* pOLV = 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_ZWNBSP : + 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_ZWNBSP: cIns = CHAR_ZWNBSP; 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(pItem)->GetValue()); + } + break; + } + + case SID_SELECTALL: + { + SdrOutliner * pOutliner = 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 (pSdrView->IsTextEdit()) + { + // Shell switch! + rSh.EndTextEdit(); + SwView& rTempView = rSh.GetView(); + rTempView.ExitDraw(); + rSh.Edit(); + return; + } + break; + case FN_DRAWTEXT_ATTR_DLG: + { + SfxItemSet aNewAttr( pSdrView->GetModel()->GetItemPool() ); + pSdrView->GetAttributes( aNewAttr ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateTextTabDialog( + GetView().GetFrameWeld(), + &aNewAttr, pSdrView )); + sal_uInt16 nResult = pDlg->Execute(); + + if (nResult == RET_OK) + { + if (pSdrView->AreObjectsMarked()) + { + 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 (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( pSdrView->GetModel()->GetItemPool() ); + pSdrView->GetAttributes( aNewAttr ); + aNewAttr.Put(SdrTextVertAdjustItem(eTVA)); + 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() ) + { + 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(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 *pSfxViewFrame = GetView().GetViewFrame(); + pSfxViewFrame->ExecuteSlot(rReq, pSfxViewFrame->GetInterface()); + } + } +} + +// State of undo + +void SwDrawTextShell::StateUndo(SfxItemSet &rSet) +{ + if ( !IsTextEdit() ) + return; + + SfxViewFrame *pSfxViewFrame = 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 ) ).append("\n"); + + SfxStringListItem aItem( nWhich ); + aItem.SetString( sList.makeStringAndClear() ); + rSet.Put( aItem ); + } + } + else + rSet.DisableItem( nWhich ); + } + break; + + default: + { + auto* pUndoManager = dynamic_cast(GetUndoManager()); + if (pUndoManager) + pUndoManager->SetView(&GetView()); + pSfxViewFrame->GetSlotState(nWhich, pSfxViewFrame->GetInterface(), &rSet); + if (pUndoManager) + pUndoManager->SetView(nullptr); + } + } + + nWhich = aIter.NextWhich(); + } +} + +void SwDrawTextShell::ExecTransliteration( SfxRequest const & rReq ) +{ + if (!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 = pSdrView->GetTextEditOutlinerView(); + + if (!pOLV) + return; + + pOLV->TransliterateText( nMode ); + } +} + +void SwDrawTextShell::ExecRotateTransliteration( SfxRequest const & rReq ) +{ + if( rReq.GetSlot() == SID_TRANSLITERATE_ROTATE_CASE ) + { + if (!pSdrView) + return; + + OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); + + if (!pOLV) + return; + + pOLV->TransliterateText( m_aRotateCase.getNextMode() ); + } +} + +// Insert special character (see SDraw: FUBULLET.CXX) + +void SwDrawTextShell::InsertSymbol(SfxRequest& rReq) +{ + OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); + if(!pOLV) + return; + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = nullptr; + if( pArgs ) + pArgs->GetItemState(GetPool().GetWhich(SID_CHARMAP), false, &pItem); + + OUString sSym; + OUString sFontName; + if ( pItem ) + { + sSym = static_cast(pItem)->GetValue(); + const SfxPoolItem* pFtItem = nullptr; + pArgs->GetItemState( GetPool().GetWhich(SID_ATTR_SPECIALCHAR), false, &pFtItem); + const SfxStringItem* pFontItem = dynamic_cast( pFtItem ); + if ( pFontItem ) + sFontName = pFontItem->GetValue(); + } + + SfxItemSet aSet(pOLV->GetAttribs()); + SvtScriptType nScript = pOLV->GetSelectedScriptType(); + std::shared_ptr aSetDlgFont(std::make_shared(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(pI->Clone())); + else + aSetDlgFont.reset(static_cast(aSet.Get( GetWhichOfScript( + SID_ATTR_CHAR_FONT, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) )).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(*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 = rView.GetViewFrame()->GetFrame().GetFrameInterface(); + ScopedVclPtr pDlg(pFact->CreateCharMapDialog(rView.GetFrameWeld(), aAllSet, xFrame)); + pDlg->Execute(); + return; + } + + // do not flicker + pOLV->HideCursor(); + SdrOutliner * pOutliner = pSdrView->GetTextEditOutliner(); + pOutliner->SetUpdateMode(false); + + SfxItemSet aOldSet( pOLV->GetAttribs() ); + SfxItemSet aFontSet( + *aOldSet.GetPool(), + svl::Items< + EE_CHAR_FONTINFO, EE_CHAR_FONTINFO, + EE_CHAR_FONTINFO_CJK, EE_CHAR_FONTINFO_CTL>{}); + 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->SetUpdateMode(true); + pOLV->ShowCursor(); + + rReq.AppendItem( SfxStringItem( GetPool().GetWhich(SID_CHARMAP), sSym ) ); + if(!aFont.GetFamilyName().isEmpty()) + rReq.AppendItem( SfxStringItem( SID_ATTR_SPECIALCHAR, aFont.GetFamilyName() ) ); + rReq.Done(); + +} + +SfxUndoManager* SwDrawTextShell::GetUndoManager() +{ + SwWrtShell &rSh = GetShell(); + pSdrView = rSh.GetDrawView(); + SdrOutliner * pOutliner = pSdrView->GetTextEditOutliner(); + return &pOutliner->GetUndoManager(); +} + +void SwDrawTextShell::GetStatePropPanelAttr(SfxItemSet &rSet) +{ + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + + SwWrtShell &rSh = GetShell(); + pSdrView = rSh.GetDrawView(); + + SfxItemSet aAttrs( pSdrView->GetModel()->GetItemPool() ); + 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 000000000..730009e1c --- /dev/null +++ b/sw/source/uibase/shells/frmsh.cxx @@ -0,0 +1,1458 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#define ShellClass_SwFrameShell +#include +#include +#include +#include +#include + +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, const OUString& 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(pArgs->GetItemState(SID_ATTR_COLUMNS, false, &pItem) == SfxItemState::SET) + nCols = static_cast(pItem)->GetValue(); + + SfxItemSet aSet(GetPool(),svl::Items{}); + 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->IsAutoUpdateFormat()) + { + 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(pItem); + const OUString& rURL = rHLinkItem.GetURL(); + const OUString& rTarget = rHLinkItem.GetTargetFrame(); + + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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; + } + 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(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 && + SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_POS_X, false, &pItem)) + { + aNewPos.setX( static_cast(pItem)->GetValue() ); + bApplyNewPos = true; + } + if (pArgs && + SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_POS_Y, false, &pItem)) + { + aNewPos.setY( static_cast(pItem)->GetValue() ); + bApplyNewPos = true; + } + + Size aNewSize = aMgr.GetSize(); + if (pArgs && + SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_WIDTH, false, &pItem)) + { + aNewSize.setWidth( static_cast< const SfxUInt32Item* >(pItem)->GetValue() ); + bApplyNewSize = true; + } + + if (pArgs && + SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_HEIGHT, false, &pItem)) + { + aNewSize.setHeight( static_cast< const SfxUInt32Item* >(pItem)->GetValue() ); + bApplyNewSize = true; + } + + if (pArgs && (pArgs->HasItem(SID_ATTR_TRANSFORM_ANGLE) || pArgs->HasItem(SID_ATTR_TRANSFORM_DELTA_ANGLE))) + { + SfxItemSet aSet(rSh.GetAttrPool(), svl::Items{} ); + rSh.GetCurAttr(aSet); + const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION); + const sal_uInt32 nOldRot(rRotation.GetValue()); + + if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_DELTA_ANGLE, false, &pItem)) + { + const sal_uInt32 nDeltaRot(static_cast(pItem)->GetValue() / 10); + 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 (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_TRANSFORM_ANGLE, false, &pItem)) + { + const sal_uInt32 nNewRot(static_cast(pItem)->GetValue() / 10); + + // 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 + { + SfxItemSet aSet( + GetPool(), + svl::Items< + 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>{}); + + // 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(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() ) ) ); + + OString sDefPage; + if(pArgs && pArgs->GetItemState(FN_FORMAT_FRAME_DLG, false, &pItem) == SfxItemState::SET) + sDefPage = OUStringToOString(static_cast(pItem)->GetValue(), RTL_TEXTENCODING_UTF8); + + aSet.Put(SfxFrameItem( SID_DOCFRAME, &GetView().GetViewFrame()->GetFrame())); + FieldUnit eMetric = ::GetDfltMetric(dynamic_cast( &GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric) )); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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); + if(nSel & SelectionType::Ole && + SfxItemState::SET == pOutSet->GetItemState(FN_KEEP_ASPECT_RATIO, true, &pItem)) + { + SwViewOption aUsrPref( *pVOpt ); + aUsrPref.SetKeepRatio(static_cast(pItem)->GetValue()); + SW_MOD()->ApplyUsrPref(aUsrPref, &GetView()); + } + if (SfxItemState::SET == pOutSet->GetItemState(FN_SET_FRM_ALT_NAME, true, &pItem)) + { + // #i73249# + rSh.SetObjTitle(static_cast(pItem)->GetValue()); + } + if (SfxItemState::SET == pOutSet->GetItemState(FN_UNO_DESCRIPTION, true, &pItem)) + rSh.SetObjDescription(static_cast(pItem)->GetValue()); + + // Template AutoUpdate + SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat(); + if(pFormat && pFormat->IsAutoUpdateFormat()) + { + rSh.AutoUpdateFrame(pFormat, *pOutSet); + // Anything which is not supported by the format must be set hard. + if(SfxItemState::SET == pOutSet->GetItemState(FN_SET_FRM_NAME, false, &pItem)) + rSh.SetFlyName(static_cast(pItem)->GetValue()); + SfxItemSet aShellSet( + GetPool(), + svl::Items< + RES_FRM_SIZE, RES_FRM_SIZE, + RES_SURROUND, RES_ANCHOR>{}); + aShellSet.Put(*pOutSet); + aMgr.SetAttrSet(aShellSet); + if(SfxItemState::SET == pOutSet->GetItemState(FN_SET_FRM_NAME, false, &pItem)) + rSh.SetFlyName(static_cast(pItem)->GetValue()); + } + else + aMgr.SetAttrSet( *pOutSet ); + + const SwFrameFormat* pCurrFlyFormat = rSh.GetFlyFrameFormat(); + if(SfxItemState::SET == + pOutSet->GetItemState(FN_PARAM_CHAIN_PREVIOUS, + false, &pItem)) + { + rSh.HideChainMarker(); + + OUString sPrevName = + static_cast(pItem)->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( + lcl_GetFrameFormatByName(rSh, sPrevName)); + SAL_WARN_IF(!pPrevFormat, "sw.ui", "No frame found!"); + if(pPrevFormat) + { + rSh.Chain(*pPrevFormat, *pCurrFlyFormat); + } + } + rSh.SetChainMarker(); + } + if(SfxItemState::SET == + pOutSet->GetItemState(FN_PARAM_CHAIN_NEXT, false, + &pItem)) + { + rSh.HideChainMarker(); + OUString sNextName = + static_cast(pItem)->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(static_cast( pCurrFlyFormat))); + } + else + sNextName.clear(); + } + + if (!sNextName.isEmpty()) + { + //needs cast - no non-const method available + SwFrameFormat* pNextFormat = const_cast( + lcl_GetFrameFormatByName(rSh, sNextName)); + SAL_WARN_IF(!pNextFormat, "sw.ui", "No frame found!"); + if(pNextFormat) + { + rSh.Chain(*const_cast( + 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); + SfxItemSet aSet(GetPool(), svl::Items{}); + 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 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()); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg( + pFact->CreateSvxObjectTitleDescDialog(GetView().GetFrameWeld(), + aTitle, aDescription )); + + if ( pDlg->Execute() == RET_OK ) + { + pDlg->GetDescription(aDescription); + pDlg->GetTitle(aTitle); + + rSh.SetObjDescription(aDescription); + rSh.SetObjTitle(aTitle); + } + } + } + break; + default: + assert(!"wrong dispatcher"); + return; + } + if ( bUpdateMgr ) + { + SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat(); + if ( bCopyToFormat && pFormat && pFormat->IsAutoUpdateFormat() ) + { + 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()) + { + SfxItemSet aSet( + rSh.GetAttrPool(), + svl::Items< + RES_LR_SPACE, RES_UL_SPACE, + RES_PRINT, RES_HORI_ORIENT>{}); + 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; + const SfxPoolItem* pItem; + + SfxItemSet aURLSet(GetPool(), svl::Items{}); + rSh.GetFlyFrameAttr( aURLSet ); + + if(SfxItemState::SET == aURLSet.GetItemState(RES_URL, true, &pItem)) + { + const SwFormatURL* pFormatURL = static_cast(pItem); + aHLinkItem.SetURL(pFormatURL->GetURL()); + aHLinkItem.SetTargetFrame(pFormatURL->GetTargetFrameName()); + aHLinkItem.SetName(rSh.GetFlyName()); + } + + aHLinkItem.SetInsertMode(static_cast(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(); + SfxItemSet aFrameSet(rSh.GetAttrPool(), svl::Items{}); + + rSh.GetFlyFrameAttr( aFrameSet ); + const SvxBoxItem& rBoxItem = aFrameSet.Get(RES_BOX); + + if (pPoolBoxItem == &rBoxItem) + bDefault = true; + + std::unique_ptr aBoxItem(rBoxItem.Clone()); + + SvxBorderLine aBorderLine; + const SfxPoolItem *pItem = nullptr; + + if(pArgs) // Any controller can sometimes deliver nothing #48169# + { + switch (rReq.GetSlot()) + { + case SID_ATTR_BORDER: + { + if (pArgs->GetItemState(RES_BOX, true, &pItem) == SfxItemState::SET) + { + std::unique_ptr aNewBox(static_cast(pItem->Clone())); + const SvxBorderLine* pBorderLine; + + if ((pBorderLine = aBoxItem->GetTop()) != nullptr) + lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine); + if ((pBorderLine = aBoxItem->GetBottom()) != nullptr) + lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine); + if ((pBorderLine = aBoxItem->GetLeft()) != nullptr) + lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine); + if ((pBorderLine = aBoxItem->GetRight()) != nullptr) + lcl_FrameGetMaxLineWidth(pBorderLine, aBorderLine); + + if(aBorderLine.GetOutWidth() == 0) + { + aBorderLine.SetBorderLineStyle( + SvxBorderLineStyle::SOLID); + aBorderLine.SetWidth( DEF_LINE_WIDTH_0 ); + } + //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 (pArgs->GetItemState(SID_FRAME_LINESTYLE, false, &pItem) == SfxItemState::SET) + { + const SvxLineItem* pLineItem = + static_cast(pItem); + + 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 (pArgs->GetItemState(SID_FRAME_LINECOLOR, false, &pItem) == SfxItemState::SET) + { + const Color& rNewColor = static_cast(pItem)->GetValue(); + + if (!aBoxItem->GetTop() && !aBoxItem->GetBottom() && + !aBoxItem->GetLeft() && !aBoxItem->GetRight()) + { + aBorderLine.SetColor( rNewColor ); + aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::TOP); + aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM); + aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::LEFT); + aBoxItem->SetLine(&aBorderLine, SvxBoxItemLine::RIGHT); + } + else + { + if ( aBoxItem->GetTop() ) + const_cast(aBoxItem->GetTop())->SetColor( rNewColor ); + if ( aBoxItem->GetBottom() ) + const_cast(aBoxItem->GetBottom())->SetColor( rNewColor ); + if ( aBoxItem->GetLeft() ) + const_cast(aBoxItem->GetLeft())->SetColor( rNewColor ); + if ( aBoxItem->GetRight() ) + const_cast(aBoxItem->GetRight())->SetColor( rNewColor ); + } + } + } + break; + } + } + if (bDefault && (aBoxItem->GetTop() || aBoxItem->GetBottom() || + aBoxItem->GetLeft() || aBoxItem->GetRight())) + { + aBoxItem->SetAllDistances(MIN_BORDER_DIST); + } + aFrameSet.Put( *aBoxItem ); + // Template AutoUpdate + SwFrameFormat* pFormat = rSh.GetSelectedFrameFormat(); + if(pFormat && pFormat->IsAutoUpdateFormat()) + { + 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()) + { + SfxItemSet aFrameSet( rSh.GetAttrPool(), svl::Items{} ); + + 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* pDoc = rSh.GetDrawView()->GetModel(); + SfxItemSet aNewAttr(pDoc->GetItemPool()); + + // get attributes from FlyFrame + rSh.GetFlyFrameAttr(aNewAttr); + + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + VclPtr pDlg(pFact->CreateSvxAreaTabDialog( + GetView().GetFrameWeld(), + &aNewAttr, + pDoc, + 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 000000000..f48e3d79e --- /dev/null +++ b/sw/source/uibase/shells/grfsh.cxx @@ -0,0 +1,1016 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define ShellClass_SwGrfShell + +#include +#include +#include +#include +#include + +#define TOOLBOX_NAME "colorbar" + +class SwGrfShell::SwExternalToolEdit + : public ExternalToolEdit +{ +private: + SwWrtShell *const m_pShell; + std::shared_ptr 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; + if(nullptr != (pGraphic = rSh.GetGraphic())) + { + 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())); + + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + 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(), aGraphic, aSize, aCropRectangle, GetView().GetViewFrame()->GetBindings()); + if (aDialog.run() == RET_OK) + { + rSh.StartAllAction(); + rSh.StartUndo(SwUndoId::START); + tools::Rectangle aScaledCropedRectangle = aDialog.GetScaledCropRectangle(); + + aCrop.SetLeft( convertMm100ToTwip( aScaledCropedRectangle.Left() )); + aCrop.SetTop( convertMm100ToTwip( aScaledCropedRectangle.Top() )); + aCrop.SetRight( convertMm100ToTwip( aScaledCropedRectangle.Right() )); + aCrop.SetBottom( convertMm100ToTwip( aScaledCropedRectangle.Bottom() )); + + Graphic aCompressedGraphic( aDialog.GetCompressedGraphic() ); + rSh.ReRead(OUString(), OUString(), const_cast(&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( + &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 ); + + SfxItemSet aSet( + GetPool(), + svl::Items< + 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_PARAM_GRF_DIALOG, FN_PARAM_GRF_DIALOG, + FN_SET_FRM_NAME, FN_KEEP_ASPECT_RATIO, + FN_SET_FRM_ALT_NAME, FN_SET_FRM_ALT_NAME, + FN_UNO_DESCRIPTION, FN_UNO_DESCRIPTION>{}); + + // 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() ); + 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 + { + SfxItemSet aTmpSet( rSh.GetAttrPool(), + svl::Items{} ); + + 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; + sal_uInt16 nCurrentRotation(0); + { // 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 + SfxItemSet aTmpSet( rSh.GetAttrPool(), svl::Items{} ); + rSh.GetCurAttr( aTmpSet ); + const SwRotationGrf& rRotation = aTmpSet.Get(RES_GRFATR_ROTATION); + nCurrentRotation = rRotation.GetValue(); + aUnrotatedSize = rRotation.GetUnrotatedSize(); + aSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE, nCurrentRotation * 10)); + } + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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); + const SfxPoolItem* pItem; + SfxItemSet* pSet = const_cast(pDlg->GetOutputItemSet()); + rReq.Done(*pSet); + // change the 2 frmsize SizeItems to the correct SwFrameSizeItem + if( SfxItemState::SET == pSet->GetItemState( + SID_ATTR_GRAF_FRMSIZE, false, &pItem )) + { + SwFormatFrameSize aSize; + const Size& rSz = static_cast(pItem)->GetSize(); + aSize.SetWidth( rSz.Width() ); + aSize.SetHeight( rSz.Height() ); + + if( SfxItemState::SET == pSet->GetItemState( + SID_ATTR_GRAF_FRMSIZE_PERCENT, false, &pItem )) + { + const Size& rRelativeSize = static_cast(pItem)->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->IsAutoUpdateFormat()) + { + pFormat->SetFormatAttr(*pSet); + SfxItemSet aShellSet( + GetPool(), + svl::Items< + RES_FRM_SIZE, RES_FRM_SIZE, + RES_SURROUND, RES_ANCHOR>{}); + aShellSet.Put(*pSet); + aMgr.SetAttrSet(aShellSet); + } + else + { + aMgr.SetAttrSet(*pSet); + } + aMgr.UpdateFlyFrame(); + + bool bApplyUsrPref = false; + if (SfxItemState::SET == pSet->GetItemState( + FN_KEEP_ASPECT_RATIO, true, &pItem )) + { + aUsrPref.SetKeepRatio( + static_cast(pItem)->GetValue() ); + bApplyUsrPref = true; + } + if( SfxItemState::SET == pSet->GetItemState( + SID_ATTR_GRAF_KEEP_ZOOM, true, &pItem )) + { + aUsrPref.SetGrfKeepZoom( + static_cast(pItem)->GetValue() ); + bApplyUsrPref = true; + } + + if( bApplyUsrPref ) + SW_MOD()->ApplyUsrPref(aUsrPref, &GetView()); + + // and now set all the graphic attributes and other stuff + if( SfxItemState::SET == pSet->GetItemState( + SID_ATTR_GRAF_GRAPHIC, true, &pItem )) + { + if( !static_cast(pItem)->GetGraphicLink().isEmpty() ) + sGrfNm = static_cast(pItem)->GetGraphicLink(); + else + sGrfNm.clear(); + + if( !static_cast(pItem)->GetGraphicFilter().isEmpty() ) + sFilterNm = static_cast(pItem)->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 ( SfxItemState::SET == pSet->GetItemState( + FN_SET_FRM_ALT_NAME, true, &pItem )) + { + // #i73249# + rSh.SetObjTitle( static_cast(pItem)->GetValue() ); + } + + if ( SfxItemState::SET == pSet->GetItemState( + FN_UNO_DESCRIPTION, true, &pItem )) + rSh.SetObjDescription( static_cast(pItem)->GetValue() ); + + // RotGrfFlyFrame: Get and process evtl. changed RotationAngle + if ( SfxItemState::SET == pSet->GetItemState(SID_ATTR_TRANSFORM_ANGLE, false, &pItem )) + { + const sal_Int32 aNewRotation((static_cast(pItem)->GetValue() / 10) % 3600); + + // RotGrfFlyFrame: Possible rotation change here, SwFlyFrameAttrMgr aMgr is available + aMgr.SetRotation(nCurrentRotation, aNewRotation, aUnrotatedSize); + } + + SfxItemSet aGrfSet( rSh.GetAttrPool(), svl::Items{} ); + aGrfSet.Put( *pSet ); + if( aGrfSet.Count() ) + rSh.SetAttrSet( aGrfSet ); + + rSh.EndUndo(SwUndoId::END); + rSh.EndAllAction(); + } + } + break; + + case FN_GRAPHIC_MIRROR_ON_EVEN_PAGES: + { + SfxItemSet aSet(rSh.GetAttrPool(), svl::Items{}); + 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) + { + SfxItemSet aGrfSet( GetShell().GetAttrPool(), svl::Items{} ); + 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(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_CONTRAST: + if( pItem ) + aGrfSet.Put( SwContrastGrf( + static_cast(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_RED: + if( pItem ) + aGrfSet.Put( SwChannelRGrf( + static_cast(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_GREEN: + if( pItem ) + aGrfSet.Put( SwChannelGGrf( + static_cast(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_BLUE: + if( pItem ) + aGrfSet.Put( SwChannelBGrf( + static_cast(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_GAMMA: + if( pItem ) + { + double fVal = static_cast(pItem)->GetValue(); + aGrfSet.Put( SwGammaGrf(fVal/100. )); + } + break; + + case SID_ATTR_GRAF_TRANSPARENCE: + if( pItem ) + aGrfSet.Put( SwTransparencyGrf( + static_cast< sal_Int8 >( static_cast(pItem )->GetValue() ) ) ); + break; + + case SID_ATTR_GRAF_INVERT: + if( pItem ) + aGrfSet.Put( SwInvertGrf( + static_cast(pItem)->GetValue() )); + break; + + case SID_ATTR_GRAF_MODE: + if( pItem ) + aGrfSet.Put( SwDrawModeGrf( + static_cast(static_cast(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( 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(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 + sal_uInt16 aRotation(0); + + if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_LEFT) + { + aRotation = 900; + } + else if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RIGHT) + { + aRotation = 2700; + } + else if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_180) + { + aRotation = 1800; + } + + if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RESET || 0 != aRotation) + { + SwWrtShell& rShell = GetShell(); + SfxItemSet aSet( rShell.GetAttrPool(), svl::Items{} ); + 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, rRotation.GetUnrotatedSize()); + } + else if(0 != aRotation) + { + const sal_uInt16 aNewRotation((aRotation + rRotation.GetValue()) % 3600); + + 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 + SfxItemSet aSet( rShell.GetAttrPool(), svl::Items{} ); + rShell.GetCurAttr( aSet ); + const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION); + bDisable = (0 == 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 + SfxItemSet aSet( rShell.GetAttrPool(), svl::Items{} ); + rShell.GetCurAttr( aSet ); + const SwRotationGrf& rRotation = aSet.Get(RES_GRFATR_ROTATION); + rSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_ANGLE, rRotation.GetValue() * 10)); + 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 000000000..5cd0e1cc5 --- /dev/null +++ b/sw/source/uibase/shells/grfshex.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 ) +{ + OUString aURL; + const SfxItemSet* pReqArgs = rReq.GetArgs(); + vcl::Window& rWindow = GetView().GetViewFrame()->GetWindow(); + bool bAPI = false, bRet = false; + + if( pReqArgs ) + { + const SfxStringItem* pStringItem = dynamic_cast( &pReqArgs->Get( rReq.GetSlot() ) ); + if( pStringItem ) + { + aURL = pStringItem->GetValue(); + bAPI = !aURL.isEmpty(); + } + } + + bool bLink(true); + if (bAPI || ::avmedia::MediaWindow::executeMediaURLDialog(rWindow.GetFrameWeld(), aURL, & bLink)) + { + Size aPrefSize; + + rWindow.EnterWait(); + + if( !::avmedia::MediaWindow::isMediaURL( aURL, "", true, &aPrefSize ) ) + { + rWindow.LeaveWait(); + + if( !bAPI ) + ::avmedia::MediaWindow::executeFormatErrorBox(rWindow.GetFrameWeld()); + } + else + { + 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 const xModel( + rSh.GetDoc()->GetDocShell()->GetModel()); + bRet = ::avmedia::EmbedMedia(xModel, aURL, realURL); + if (!bRet) { return bRet; } + } + + 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(); + } + } + + 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 000000000..90904b37d --- /dev/null +++ b/sw/source/uibase/shells/langhelper.cxx @@ -0,0 +1,588 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +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(nScriptType) ) );//pEditEngine->GetScriptType(aSelection) + + // get keyboard language + OUString aKeyboardLang; + LanguageType nLang = LANGUAGE_DONTKNOW; + + vcl::Window* pWin = rEditView.GetWindow(); + if(pWin) + nLang = pWin->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( 4 ); + aSeq[0] = aCurrentLang; + aSeq[1] = aScriptTypesInUse; + aSeq[2] = aKeyboardLang; + aSeq[3] = 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; + SfxItemSet aEditAttr(pOLV->GetAttribs()); + ESelection aSelection = pOLV->GetSelection(); + EditView & rEditView = pOLV->GetEditView(); + EditEngine * pEditEngine = rEditView.GetEditEngine(); + + // get the language + OUString aNewLangText; + + const SfxStringItem* pItem = rReq.GetArg(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 *pViewFrame = rView.GetViewFrame(); + + if (aNewLangText == "*" ) + { + // open the dialog "Tools/Options/Language Settings - Language" + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateVclDialog( rView.GetFrameWeld(), SID_LANGUAGE_OPTIONS )); + pDlg->Execute(); + } + else + { + // setting the new language... + if (!aNewLangText.isEmpty()) + { + const OUString aSelectionLangPrefix("Current_"); + const OUString aParagraphLangPrefix("Paragraph_"); + const OUString aDocumentLangPrefix("Default_"); + + 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(), ""); + bForSelection = true; + } + else if (-1 != (nPos = aNewLangText.indexOf( aParagraphLangPrefix ))) + { + // ... for the current paragraph language + aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), ""); + bForSelection = true; + bForParagraph = true; + } + else if (-1 != (nPos = aNewLangText.indexOf( aDocumentLangPrefix ))) + { + // ... as default document language + aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), ""); + 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 ); + + // ugly hack, as it seems that EditView/EditEngine does not update their spellchecking marks + // when setting a new language attribute + if (bForSelection) + { + const SwViewOption* pVOpt = rView.GetWrtShellPtr()->GetViewOptions(); + EEControlBits nCntrl = pEditEngine->GetControlWord(); + // turn off + nCntrl &= ~EEControlBits::ONLINESPELLING; + pEditEngine->SetControlWord(nCntrl); + + //turn back on + if (pVOpt->IsOnlineSpell()) + nCntrl |= EEControlBits::ONLINESPELLING; + else + nCntrl &= ~EEControlBits::ONLINESPELLING; + pEditEngine->SetControlWord(nCntrl); + + pEditEngine->CompleteOnlineSpelling(); + rEditView.Invalidate(); + } + + 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 + pViewFrame->GetBindings().Invalidate( rReq.GetSlot() ); + + rReq.Done(); + return bRestoreSelection; + } + + void SetLanguage( SwWrtShell &rWrtSh, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet ) + { + SetLanguage( rWrtSh, nullptr , ESelection(), rLangText, bIsForSelection, rCoreSet ); + } + + void SetLanguage( SwWrtShell &rWrtSh, OutlinerView const * pOLV, const ESelection& rSelection, const OUString &rLangText, bool bIsForSelection, SfxItemSet &rCoreSet ) + { + const LanguageType nLang = SvtLanguageTable::GetLanguageType( rLangText ); + if (nLang != LANGUAGE_DONTKNOW) + { + EditEngine* pEditEngine = pOLV ? pOLV->GetEditView().GetEditEngine() : nullptr; + OSL_ENSURE( !pOLV || pEditEngine, "OutlinerView without EditEngine???" ); + + //get ScriptType + sal_uInt16 nLangWhichId = 0; + bool bIsSingleScriptType = true; + switch (SvtLanguageOptions::GetScriptTypeOfLanguage( nLang )) + { + case SvtScriptType::LATIN : nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE) : sal_uInt16(RES_CHRATR_LANGUAGE); break; + case SvtScriptType::ASIAN : nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE_CJK) : sal_uInt16(RES_CHRATR_CJK_LANGUAGE); break; + case SvtScriptType::COMPLEX : nLangWhichId = pEditEngine ? sal_uInt16(EE_CHAR_LANGUAGE_CTL) : sal_uInt16(RES_CHRATR_CTL_LANGUAGE); break; + default: + bIsSingleScriptType = false; + OSL_FAIL("unexpected case" ); + } + if (bIsSingleScriptType) + { + // 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 ) ); + + //Resolves: fdo#35282 Clear the language from all Text Styles, and + //fallback to default document language + const SwTextFormatColls *pColls = rWrtSh.GetDoc()->GetTextFormatColls(); + for(size_t i = 0, nCount = pColls->size(); i < nCount; ++i) + { + SwTextFormatColl &rTextColl = *(*pColls)[ i ]; + rTextColl.ResetFormatAttr(nLangWhichId); + } + //Resolves: fdo#35282 Clear the language from all Character Styles, + //and fallback to default document language + const SwCharFormats *pCharFormats = rWrtSh.GetDoc()->GetCharFormats(); + for(size_t i = 0, nCount = pCharFormats->size(); i < nCount; ++i) + { + SwCharFormat &rCharFormat = *(*pCharFormats)[ i ]; + rCharFormat.ResetFormatAttr(nLangWhichId); + } + + // #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 + { + std::set aAttribs; + for (sal_uInt16 i : aLangWhichId_Writer) + { + rWrtSh.SetDefault( SvxLanguageItem( LANGUAGE_NONE, i ) ); + aAttribs.insert( i ); + } + + // 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 ); + } + else + { + std::set aAttribs; + aAttribs.insert( RES_CHRATR_LANGUAGE ); + aAttribs.insert( RES_CHRATR_CJK_LANGUAGE ); + aAttribs.insert( RES_CHRATR_CTL_LANGUAGE ); + rWrtSh.ResetAttr( aAttribs ); + } + } + + /// @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, sal_uInt16 nLangWhichId ) + { + SfxItemSet aSet( rSh.GetAttrPool(), {{nLangWhichId, nLangWhichId}} ); + rSh.GetCurAttr( aSet ); + + return GetLanguage(aSet,nLangWhichId); + } + + LanguageType GetLanguage( SfxItemSet const & aSet, sal_uInt16 nLangWhichId ) + { + + LanguageType nLang = LANGUAGE_SYSTEM; + + const SfxPoolItem *pItem = nullptr; + SfxItemState nState = aSet.GetItemState( nLangWhichId, true, &pItem ); + if (nState > SfxItemState::DEFAULT && pItem) + { + // the item is set and can be used + nLang = dynamic_cast(*pItem).GetLanguage(); + } + else if (nState == SfxItemState::DEFAULT) + { + // since the attribute is not set: retrieve the default value + nLang = dynamic_cast(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 + sal_uInt16 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 sal_uInt16 aScriptTypes[3] = + { + RES_CHRATR_LANGUAGE, + RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CTL_LANGUAGE + }; + nCurrentLang = LANGUAGE_NONE; + for (sal_uInt16 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 + sal_uInt16 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 sal_uInt16 aScriptTypes[3] = + { + EE_CHAR_LANGUAGE, + EE_CHAR_LANGUAGE_CJK, + EE_CHAR_LANGUAGE_CTL + }; + nCurrentLang = LANGUAGE_NONE; + for (sal_uInt16 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->GetNode().GetTextNode(); + if (pNode) + { + aText = pNode->GetText(); + if (!aText.isEmpty()) + { + sal_Int32 nEnd = pCursor->GetPoint()->nContent.GetIndex(); + // 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 ); + #if OSL_DEBUG_LEVEL > 1 + OUString aSelText; + rWrtSh.GetSelectedText( aSelText ); + (void) aSelText; + #endif + } +} + +/* 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 000000000..a8d7eb91f --- /dev/null +++ b/sw/source/uibase/shells/listsh.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ShellClass_SwListShell +#include +#include + +#include + +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 ) ) + { + 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 * pFrame = GetView().GetViewFrame(); + + rReq.Done(); + rSh.NumUpDown( nSlot == FN_NUM_BULLET_DOWN ); + pFrame->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_OFF: + { + rReq.Ignore(); + SfxRequest aReq( GetView().GetViewFrame(), FN_NUM_BULLET_ON ); + aReq.AppendItem( SfxBoolItem( FN_PARAM_1, false ) ); + aReq.Done(); + rSh.DelNumRules(); + 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(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 000000000..932b2feb6 --- /dev/null +++ b/sw/source/uibase/shells/mediash.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ShellClass_SwMediaShell +#include +#include +#include + +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 ) + { + const SfxItemSet* pArgs = rReq.GetArgs(); + 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() ) + { + const SfxPoolItem* pItem; + + if( !pArgs || ( SfxItemState::SET != pArgs->GetItemState( SID_AVMEDIA_TOOLBOX, false, &pItem ) ) ) + pItem = nullptr; + + if( pItem ) + { + std::unique_ptr pMarkList(new SdrMarkList( pSdrView->GetMarkedObjectList() )); + + if( 1 == pMarkList->GetMarkCount() ) + { + SdrObject* pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj(); + + if( dynamic_cast< const SdrMediaObj *>( pObj ) ) + { + static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( pObj->GetViewContact() ).executeMediaItem( + static_cast< const ::avmedia::MediaItem& >( *pItem ) ); + } + } + } + } + } + break; + + default: + break; + } + + if( pSdrView->GetModel()->IsChanged() ) + GetShell().SetModified(); + else if( bChanged ) + pSdrView->GetModel()->SetChanged(); + } +} + +void SwMediaShell::GetMediaState(SfxItemSet &rSet) +{ + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while( nWhich ) + { + if( SID_AVMEDIA_TOOLBOX == nWhich ) + { + SwWrtShell& rSh = GetShell(); + SdrView* pView = rSh.GetDrawView(); + + if( pView ) + { + bool bDisable = true; + std::unique_ptr pMarkList(new SdrMarkList( pView->GetMarkedObjectList() )); + + if( 1 == pMarkList->GetMarkCount() ) + { + SdrObject* pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj(); + + if( dynamic_cast< const SdrMediaObj *>( pObj ) ) + { + ::avmedia::MediaItem aItem( SID_AVMEDIA_TOOLBOX ); + + static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( pObj->GetViewContact() ).updateMediaItem( aItem ); + rSet.Put( aItem ); + bDisable = false; + } + } + + if( bDisable ) + rSet.DisableItem( SID_AVMEDIA_TOOLBOX ); + } + } + + nWhich = aIter.NextWhich(); + } +} + +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 000000000..b5b9021cc --- /dev/null +++ b/sw/source/uibase/shells/navsh.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/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#define ShellClass_SwNavigationShell +#include +#include + +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); + 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 000000000..b8207d200 --- /dev/null +++ b/sw/source/uibase/shells/olesh.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include + +#define ShellClass_SwOleShell +#include +#include + +SFX_IMPL_INTERFACE(SwOleShell, SwFrameShell) + +void SwOleShell::InitInterface_Impl() +{ + GetStaticInterface()->RegisterPopupMenu("oleobject"); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Ole_Toolbox); +} + +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 000000000..76de1a6dc --- /dev/null +++ b/sw/source/uibase/shells/slotadd.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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define avmedia_MediaItem ::avmedia::MediaItem + +#include +#include +#include +#include + +#define SFX_TYPEMAP +#include +#include + +/* 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 000000000..d2e238044 --- /dev/null +++ b/sw/source/uibase/shells/tabsh.cxx @@ -0,0 +1,1602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ShellClass_SwTableShell +#include +#include + +#include + +#include + +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); +} + + +static const sal_uInt16 aUITableAttrRange[] = +{ + XATTR_FILL_FIRST, XATTR_FILL_LAST, + FN_PARAM_TABLE_NAME, FN_PARAM_TABLE_NAME, + FN_PARAM_TABLE_HEADLINE, FN_PARAM_TABLE_HEADLINE, + FN_PARAM_TABLE_SPACE, FN_PARAM_TABLE_SPACE, + FN_TABLE_REP, FN_TABLE_REP, + SID_RULER_BORDERS, SID_RULER_BORDERS, + RES_LR_SPACE, RES_UL_SPACE, + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_SHADOW, + RES_BOX, RES_SHADOW, + RES_BACKGROUND, RES_BACKGROUND, + SID_BACKGRND_DESTINATION, SID_BACKGRND_DESTINATION, + SID_HTML_MODE, SID_HTML_MODE, + SID_ATTR_BRUSH_ROW, SID_ATTR_BRUSH_TABLE, + RES_PAGEDESC, RES_BREAK, + RES_KEEP, RES_KEEP, + RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT, + FN_TABLE_SET_VERT_ALIGN, FN_TABLE_SET_VERT_ALIGN, + RES_FRAMEDIR, RES_FRAMEDIR, + RES_ROW_SPLIT, RES_ROW_SPLIT, + FN_TABLE_BOX_TEXTORIENTATION, FN_TABLE_BOX_TEXTORIENTATION, +// #i29550# + RES_COLLAPSING_BORDERS, RES_COLLAPSING_BORDERS, +// <-- collapsing borders + 0 +}; + +const sal_uInt16* 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 lcl_TableParamToItemSet( SfxItemSet& rSet, SwWrtShell &rSh ) +{ + std::shared_ptr 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 aBrush(std::make_unique(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 aBoxDirection(std::make_unique(SvxFrameDirection::Environment, RES_FRAMEDIR)); + if(rSh.GetBoxDirection( aBoxDirection )) + { + aBoxDirection->SetWhich(FN_TABLE_BOX_TEXTORIENTATION); + rSet.Put(*aBoxDirection); + } + + bool bSelectAll = rSh.StartsWithTable() && 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 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(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 ); + const SfxPoolItem* pItem = nullptr; + + if(SfxItemState::SET == rSet.GetItemState(SID_BACKGRND_DESTINATION, false, &pItem)) + { + SwViewOption aUsrPref( *rSh.GetViewOptions() ); + aUsrPref.SetTableDest(static_cast(static_cast(pItem)->GetValue())); + SW_MOD()->ApplyUsrPref(aUsrPref, &rSh.GetView()); + } + bool bBorder = ( SfxItemState::SET == rSet.GetItemState( RES_BOX ) || + SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER ) ); + pItem = nullptr; + bool bBackground = SfxItemState::SET == rSet.GetItemState( RES_BACKGROUND, false, &pItem ); + const SfxPoolItem* pRowItem = nullptr, *pTableItem = nullptr; + bBackground |= SfxItemState::SET == rSet.GetItemState( SID_ATTR_BRUSH_ROW, false, &pRowItem ); + bBackground |= SfxItemState::SET == rSet.GetItemState( SID_ATTR_BRUSH_TABLE, false, &pTableItem ); + const SfxPoolItem* pSplit = nullptr; + bool bRowSplit = SfxItemState::SET == rSet.GetItemState( RES_ROW_SPLIT, false, &pSplit ); + const SfxPoolItem* pBoxDirection = nullptr; + bool bBoxDirection = SfxItemState::SET == rSet.GetItemState( FN_TABLE_BOX_TEXTORIENTATION, false, &pBoxDirection ); + 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(pItem) + rSh.SetBoxBackground( *static_cast(pItem) ); + if(pRowItem) + { + std::unique_ptr aBrush(static_cast(pRowItem->Clone())); + aBrush->SetWhich(RES_BACKGROUND); + rSh.SetRowBackground(*aBrush); + } + if(pTableItem) + { + std::unique_ptr aBrush(static_cast(pTableItem->Clone())); + aBrush->SetWhich(RES_BACKGROUND); + rSh.SetTabBackground( *aBrush ); + } + } + + if(bBoxDirection) + { + SvxFrameDirectionItem aDirection( SvxFrameDirection::Environment, RES_FRAMEDIR ); + aDirection.SetValue(static_cast< const SvxFrameDirectionItem* >(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(*static_cast(pSplit)); + } + + if(!bTableSel) + { + rSh.ClearMark(); + } + rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); + } + + rSh.EndAllAction(); + } + + SwTabCols aTabCols; + bool bTabCols = false; + SwTableRep* pRep = nullptr; + SwFrameFormat *pFormat = rSh.GetTableFormat(); + SfxItemSet aSet( rSh.GetAttrPool(), svl::Items{} ); + if(SfxItemState::SET == rSet.GetItemState( FN_TABLE_REP, false, &pItem )) + { + pRep = static_cast(static_cast(pItem)->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(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(rSet).ClearItem( SID_ATTR_LRSPACE ); + + if(pRep->HasColsChanged()) + { + bTabCols = true; + } + } + + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_TABLE_HEADLINE, false, &pItem)) + rSh.SetRowsToRepeat( static_cast(pItem)->GetValue() ); + + if( SfxItemState::SET == rSet.GetItemState( FN_TABLE_SET_VERT_ALIGN, false, &pItem)) + rSh.SetBoxAlign(static_cast(pItem)->GetValue()); + + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_TABLE_NAME, false, &pItem )) + rSh.SetTableName( *pFormat, static_cast(pItem)->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 + }; + for( const sal_uInt16* pIds = aIds; *pIds; ++pIds ) + if( SfxItemState::SET == rSet.GetItemState( *pIds, false, &pItem)) + aSet.Put( *pItem ); + + if( aSet.Count() ) + rSh.SetTableAttr( aSet ); + + if(bTabCols) + { + rSh.GetTabCols( aTabCols ); + bool bSingleLine = pRep->FillTabCols( aTabCols ); + rSh.SetTabCols( aTabCols, bSingleLine ); + } + + 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()); +} + +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 aBox(std::make_shared(RES_BOX)); + SfxItemSet aCoreSet( GetPool(), + svl::Items{}); + SvxBoxInfoItem aCoreInfo( SID_ATTR_BORDER_INNER ); + aCoreSet.Put(aCoreInfo); + rSh.GetTabBorders( aCoreSet ); + const SvxBoxItem& rCoreBox = aCoreSet.Get(RES_BOX); + const SfxPoolItem *pBoxItem = nullptr; + if ( pArgs->GetItemState(RES_BOX, true, &pBoxItem) == SfxItemState::SET ) + { + aBox.reset(static_cast(pBoxItem->Clone())); + sal_uInt16 nDefValue = MIN_BORDER_DIST; + if ( !rReq.IsAPI() ) + nDefValue = 55; + if (!rReq.IsAPI() || aBox->GetSmallestDistance() < MIN_BORDER_DIST) + { + for( SvxBoxItemLine k : o3tl::enumrange() ) + 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 aInfo(std::make_shared(SID_ATTR_BORDER_INNER)); + if (pArgs->GetItemState(SID_ATTR_BORDER_INNER, true, &pBoxItem) == SfxItemState::SET) + { + aInfo.reset(static_cast(pBoxItem->Clone())); + } + else if( pArgs->GetItemState(SDRATTR_TABLE_BORDER_INNER, true, &pBoxItem) == SfxItemState::SET ) + { + aInfo.reset(static_cast(pBoxItem->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( DEF_LINE_WIDTH_5 ); + } + + 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( &rSh.GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + std::shared_ptr pTableRep(::lcl_TableParamToItemSet(aCoreSet, rSh)); + + aCoreSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(GetView().GetDocShell()))); + rSh.GetTableAttr(aCoreSet); + // GetTableAttr overwrites the background! + std::unique_ptr aBrush(std::make_unique(RES_BACKGROUND)); + if(rSh.GetBoxBackground(aBrush)) + aCoreSet.Put( *aBrush ); + else + aCoreSet.InvalidateItem( RES_BACKGROUND ); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + VclPtr pDlg(pFact->CreateSwTableTabDlg(GetView().GetFrameWeld(), &aCoreSet, &rSh)); + + if (pDlg) + { + if (pItem) + pDlg->SetCurPageId(OUStringToOString(static_cast(pItem)->GetValue(), RTL_TEXTENCODING_UTF8)); + + auto pRequest = std::make_shared(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + + auto xPaM(std::make_shared(*rSh.GetCursor(), nullptr)); // tdf#135636 make a copy to use at later apply + pDlg->StartExecuteAsync([pDlg, pRequest, pTableRep, &rBindings, &rSh, xPaM](sal_Int32 nResult){ + if (RET_OK == nResult) + { + rSh.SetSelection(*xPaM); // tdf#135636 set the table selected at dialog launch as current selection + + 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: + { + SwView* pView = GetActiveView(); + if(pView) + { + FieldUnit eMetric = ::GetDfltMetric(dynamic_cast( pView) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + SvNumberFormatter* pFormatter = rSh.GetNumberFormatter(); + SfxItemSet aCoreSet( + GetPool(), + svl::Items< + SID_ATTR_NUMBERFORMAT_VALUE, + SID_ATTR_NUMBERFORMAT_INFO>{}); + + SfxItemSet aBoxSet( *aCoreSet.GetPool(), + svl::Items{} ); + rSh.GetTableBoxFormulaAttrs( aBoxSet ); + + SfxItemState eState = aBoxSet.GetItemState(RES_BOXATR_FORMAT); + if(eState == SfxItemState::DEFAULT) + { + aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, + pFormatter->GetFormatIndex(NF_TEXT, LANGUAGE_SYSTEM))); + } + else + aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, + aBoxSet.Get( + RES_BOXATR_FORMAT ).GetValue() )); + + OUString sCurText( rSh.GetTableBoxText() ); + aCoreSet.Put( SvxNumberInfoItem( pFormatter, + aBoxSet.Get( + RES_BOXATR_VALUE).GetValue(), + sCurText, SID_ATTR_NUMBERFORMAT_INFO )); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateNumFormatDialog(GetView().GetFrameWeld(), aCoreSet)); + + if (RET_OK == pDlg->Execute()) + { + const SvxNumberInfoItem* pNumberFormatItem + = GetView().GetDocShell()->GetItem( SID_ATTR_NUMBERFORMAT_INFO ); + + if( pNumberFormatItem ) + { + for ( sal_uInt32 key : pNumberFormatItem->GetDelFormats() ) + pNumberFormatItem->GetNumberFormatter()->DeleteEntry( key ); + } + + const SfxPoolItem* pNumberFormatValueItem = nullptr; + if( SfxItemState::SET == pDlg->GetOutputItemSet()->GetItemState( + SID_ATTR_NUMBERFORMAT_VALUE, false, &pNumberFormatValueItem )) + { + SfxItemSet aBoxFormatSet( *aCoreSet.GetPool(), + svl::Items{} ); + aBoxFormatSet.Put( SwTableBoxNumFormat( + static_cast(pNumberFormatValueItem)->GetValue() )); + rSh.SetTableBoxFormulaAttrs( aBoxFormatSet ); + + } + } + } + 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(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 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 pDlg(pFact->CreateSwAutoFormatDlg(GetView().GetFrameWeld(), &rSh)); + pDlg->Execute(); + break; + } + case FN_TABLE_SET_ROW_HEIGHT: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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(pItem)->GetValue(); + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_INSERT_AFTER, true, &pItem)) + bAfter = static_cast(pItem)->GetValue(); + } + else if( !rReq.IsAPI() ) + { + SwSelBoxes aBoxes; + ::GetTableSel( rSh, aBoxes ); + if ( !aBoxes.empty() ) + { + long maxX = 0; + long maxY = 0; + long minX = std::numeric_limits::max(); + long minY = std::numeric_limits::max(); + long nbBoxes = aBoxes.size(); + for ( 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)); + SfxItemSet aSet( GetPool(), svl::Items{}); + 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 pDlg(pFact->CreateSvxInsRowColDlg(GetView().GetFrameWeld(), + nSlot == FN_TABLE_INSERT_COL_DLG, pSlot->GetCommand())); + if( pDlg->Execute() == 1 ) + { + const sal_uInt16 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* pVFrame = GetView().GetViewFrame(); + if( pVFrame ) + pVFrame->GetDispatcher()->ExecuteList(nDispatchSlot, + SfxCallMode::SYNCHRON|SfxCallMode::RECORD, + { &aCountItem, &aAfter }); + } + } + break; + } + case FN_TABLE_SPLIT_CELLS: + { + long nCount=0; + bool bHorizontal=true; + bool bProportional = false; + const SfxInt32Item* pSplit = rReq.GetArg(FN_TABLE_SPLIT_CELLS); + const SfxBoolItem* pHor = rReq.GetArg(FN_PARAM_1); + const SfxBoolItem* pProp = rReq.GetArg(FN_PARAM_2); + if ( pSplit ) + { + nCount = pSplit->GetValue(); + if ( pHor ) + bHorizontal = pHor->GetValue(); + if ( pProp ) + bProportional = pProp->GetValue(); + } + else + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + const long nMaxVert = rSh.GetAnyCurRect( CurRectType::Frame ).Width() / MINLAY; + ScopedVclPtr pDlg(pFact->CreateSvxSplitTableDialog(GetView().GetFrameWeld(), rSh.IsTableVertical(), nMaxVert)); + if(rSh.IsSplitVerticalByDefault()) + pDlg->SetSplitVerticalByDefault(); + if( pDlg->Execute() == RET_OK ) + { + nCount = pDlg->GetCount(); + bHorizontal = pDlg->IsHorizontal(); + bProportional = pDlg->IsProportional(); + rReq.AppendItem( SfxInt32Item( FN_TABLE_SPLIT_CELLS, nCount ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bHorizontal ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_2, bProportional ) ); + + // tdf#60242: remember choice for next time + bool bVerticalWasChecked = !pDlg->IsHorizontal(); + rSh.SetSplitVerticalByDefault(bVerticalWasChecked); + } + } + + 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(FN_PARAM_1); + if( pType ) + { + switch( static_cast(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(pType->GetValue())) ; + break; + default: ;//wrong parameter, do nothing + } + } + else + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSplitTableDialog(GetView().GetFrameWeld(), rSh)); + pDlg->Execute(); + rReq.AppendItem( SfxUInt16Item( FN_PARAM_1, static_cast(pDlg->GetSplitMode()) ) ); + bCallDone = true; + } + break; + } + + case FN_TABLE_MERGE_TABLE: + { + bool bPrev = rSh.CanMergeTable(); + bool bNext = rSh.CanMergeTable( false ); + + if( bPrev && bNext ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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* pVFrame = GetView().GetViewFrame(); + pVFrame->GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::SYNCHRON); + const sal_uInt16 nId = SwInputChild::GetChildWindowId(); + SwInputChild* pChildWin = static_cast(pVFrame-> + 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(SID_ATTR_TABLE_ROW_HEIGHT); + if (pItem2) + { + long nNewHeight = pItem2->GetValue(); + std::unique_ptr 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(SID_ATTR_TABLE_COLUMN_WIDTH); + if (pItem2) + { + 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(pItem) ); + aULSpace.SetWhich( RES_UL_SPACE ); + ::lcl_SetAttr( rSh, aULSpace ); + } + break; + + case SID_ATTR_LRSPACE: + if(pItem) + { + SfxItemSet aSet( GetPool(), svl::Items{} ); + SvxLRSpaceItem aLRSpace( *static_cast(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(pItem)->GetValue()); + SfxItemSet aSet(GetPool(), svl::Items{} ); + aSet.Put(aSplit); + rSh.SetTableAttr(aSet); + } + break; + + case SID_ATTR_PARA_KEEP: + if ( pItem ) + { + SvxFormatKeepItem aKeep( *static_cast(pItem) ); + aKeep.SetWhich( RES_KEEP ); + SfxItemSet aSet(GetPool(), svl::Items{} ); + aSet.Put(aKeep); + rSh.SetTableAttr(aSet); + } + break; + case FN_TABLE_ROW_SPLIT : + { + const SfxBoolItem* pBool = static_cast(pItem); + std::unique_ptr 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 pSz = rSh.GetRowHeight(); + if ( pSz ) + { + if ( SwFrameSize::Variable == pSz->GetHeightSizeType() ) + rSet.DisableItem( nSlot ); + } + 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 )) + rSet.DisableItem( nSlot ); + } + break; + case FN_TABLE_DELETE_COL: + { + SwSelBoxes aBoxes; + ::GetTableSel( rSh, aBoxes, SwTableSearchType::Col ); + if( ::HasProtectedCells( aBoxes )) + 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 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 pHeight = rSh.GetRowHeight(); + if (pHeight) + { + 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).getStr()); + } + } + 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).getStr()); + } + + 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) +{ + SfxItemSet aCoreSet( GetPool(), + svl::Items{} ); + 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) + 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) +{ + SfxItemSet aCoreSet( GetPool(), + svl::Items{}); + 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(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 ) + { + SfxItemSet aBoxSet( GetPool(), svl::Items{} ); + 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 000000000..0303576e2 --- /dev/null +++ b/sw/source/uibase/shells/textdrw.cxx @@ -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 . + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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(OBJ_FM_BUTTON); + pSdrView->SetEditMode(false); + + Point aStartPos(rSh.GetCharRect().Pos() + Point(0, 1)); + + rSh.StartAction(); + rSh.StartUndo( SwUndoId::UI_INSERT_URLBTN ); + if (rSh.BeginCreate(OBJ_FM_BUTTON, 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( 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 000000000..9b7d3b10a --- /dev/null +++ b/sw/source/uibase/shells/textfld.cxx @@ -0,0 +1,1096 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace nsSwDocInfoSubType; + +static OUString lcl_BuildTitleWithRedline( const SwRangeRedline *pRedline ) +{ + const OUString sTitle(SwResId(STR_REDLINE_COMMENT)); + + const char* pResId = nullptr; + 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(); + if( pField ) + { + switch ( pField->GetTypeId() ) + { + case SwFieldTypesEnum::DDE: + { + ::sfx2::SvBaseLink& rLink = static_cast(pField->GetTyp())-> + GetBaseLink(); + if(rLink.IsVisible()) + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateLinksDialog(GetView().GetFrameWeld(), &rSh.GetLinkManager(), false, &rLink)); + pDlg->Execute(); + } + break; + } + default: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwFieldEditDlg( GetView() )); + pDlg->Execute(); + } + } + } + break; + } + case FN_EXECUTE_MACROFIELD: + { + SwField* pField = rSh.GetCurField(); + if(pField && pField->GetTyp()->Which() == SwFieldIds::Macro) + { + + const OUString& rMacro = static_cast(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( + SwCursorShell::GetTextFieldAtCursor(rSh.GetCursor(), true)))) + { + rSh.SttSelect(); + rSh.SelectText( + SwCursorShell::StartOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) + 1, + SwCursorShell::EndOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) - 1 ); + } + else + { + rSh.StartInputFieldDlg(rSh.GetCurField(true), false, false, GetView().GetFrameWeld()); + } + bRet = true; + } + + rReq.SetReturnValue( SfxBoolItem( nSlot, bRet )); + } + break; + + default: + bMore = true; + } + if(bMore) + { + // 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(pItem)->GetValue(); + OUString aPar2; + sal_Int32 nCommand = 0; + + if( SfxItemState::SET == pArgs->GetItemState( FN_PARAM_FIELD_TYPE, + false, &pItem )) + nType = static_cast(static_cast(pItem)->GetValue()); + aPar1 += OUStringChar(DB_DELIM); + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_1, false, &pItem )) + { + aPar1 += static_cast(pItem)->GetValue(); + } + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_3, false, &pItem )) + nCommand = static_cast(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(pItem)->GetValue(); + } + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_FIELD_CONTENT, false, &pItem )) + aPar2 = static_cast(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_FIELD_FORMAT, false, &pItem )) + nFormat = static_cast(pItem)->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(pItem)->GetValue(); + OUString aPar2; + sal_Unicode cSeparator = ' '; + + if( SfxItemState::SET == pArgs->GetItemState( FN_PARAM_FIELD_TYPE, + false, &pItem )) + nType = static_cast(static_cast(pItem)->GetValue()); + if( SfxItemState::SET == pArgs->GetItemState( FN_PARAM_FIELD_SUBTYPE, + false, &pItem )) + nSubType = static_cast(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_FIELD_CONTENT, false, &pItem )) + aPar2 = static_cast(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_FIELD_FORMAT, false, &pItem )) + nFormat = static_cast(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( + FN_PARAM_3, false, &pItem )) + { + OUString sTmp = static_cast(pItem)->GetValue(); + if(!sTmp.isEmpty()) + cSeparator = sTmp[0]; + } + 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* pVFrame = GetView().GetViewFrame(); + pVFrame->ToggleChildWindow(FN_INSERT_FIELD); + bRes = pVFrame->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* pVFrame = GetView().GetViewFrame(); + if (!pVFrame->HasChildWindow(FN_INSERT_FIELD)) + pVFrame->ToggleChildWindow(FN_INSERT_FIELD); // Show dialog + + // Switch Fielddlg at a new TabPage + sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId(); + SwFieldDlgWrapper *pWrp = static_cast(pVFrame->GetChildWindow(nId)); + if (pWrp) + pWrp->ShowReferencePage(); + rReq.Ignore(); + } + break; + case FN_DELETE_COMMENT: + { + const SvxPostItIdItem* pIdItem = rReq.GetArg(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_RESOLVE_NOTE: + { + const SvxPostItIdItem* pIdItem = rReq.GetArg(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(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(nSlot); + if ( pNoteItem && GetView().GetPostItMgr() ) + GetView().GetPostItMgr()->Hide( pNoteItem->GetValue() ); + } + break; + case FN_REPLY: + { + const SvxPostItIdItem* pIdItem = rReq.GetArg(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(SID_ATTR_POSTIT_TEXT)) + sText = pTextItem->GetValue(); + pMgr->RegisterAnswerText(sText); + pWin->ExecuteCommand(nSlot); + } + } + } + } + break; + case FN_POSTIT: + { + rSh.InsertPostIt(aFieldMgr, rReq); + } + break; + case SID_EDIT_POSTIT: + { + const SvxPostItIdItem* pIdItem = rReq.GetArg(SID_ATTR_POSTIT_ID); + if (pIdItem && !pIdItem->GetValue().isEmpty()) + { + const SvxPostItTextItem* pTextItem = rReq.GetArg(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(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(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(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(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 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(pItem)->GetValue(); + const SfxStringItem* pType = rReq.GetArg(FN_PARAM_2); + const SfxBoolItem* pIsUrl = rReq.GetArg(FN_PARAM_1); + if ( pType ) + aType = pType->GetValue(); + if ( pIsUrl ) + bIsUrl = pIsUrl->GetValue(); + + SwScriptField* pField = static_cast(aMgr.GetCurField()); + bNew = !pField || (pField->GetTyp()->Which() != SwFieldIds::Script); + bUpdate = pField && ( bIsUrl != static_cast(pField->GetFormat()) || pField->GetPar2() != aType || pField->GetPar1() != aText ); + } + else + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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 : + { + nInsertType = SwFieldTypesEnum::Date; + bIsText = false; + // use long date format for Hungarian + SwPaM* pCursorPos = rSh.GetCursor(); + if( pCursorPos ) + { + LanguageType nLang = pCursorPos->GetPoint()->nNode.GetNode().GetTextNode()->GetLang(pCursorPos->GetPoint()->nContent.GetIndex()); + if (nLang == LANGUAGE_HUNGARIAN) + nInsertFormat = rSh.GetNumberFormatter()->GetFormatIndex(NF_DATE_SYSTEM_LONG, nLang); + } + goto FIELD_INSERT; + } + case FN_INSERT_FLD_TIME : + nInsertType = SwFieldTypesEnum::Time; + 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: + { + 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 const 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()->nNode, pCursorPos->GetPoint()->nContent.GetIndex() - ODF_FORMFIELD_DEFAULT_LENGTH, + pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex()); + pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMTEXT, + aFieldPam.Start()); + } + } + + 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()->nNode, pCursorPos->GetPoint()->nContent.GetIndex() - ODF_FORMFIELD_DEFAULT_LENGTH, + pCursorPos->GetPoint()->nNode, pCursorPos->GetPoint()->nContent.GetIndex()); + 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; + 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 ); + } + } + break; + + case FN_EDIT_FIELD: + { + if( !bGetField ) + { + pField = rSh.GetCurField(); + 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(pField->GetTyp())->GetBaseLink().IsVisible()) + { + // nested links cannot be edited + 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* pVFrame = GetView().GetViewFrame(); + //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active + if(!pVFrame->IsInModalMode() && + pVFrame->KnowsChildWindow(FN_INSERT_FIELD) && !pVFrame->HasChildWindow(FN_INSERT_FIELD_DATA_ONLY) ) + rSet.Put(SfxBoolItem( FN_INSERT_FIELD, pVFrame->HasChildWindow(nWhich))); + else + rSet.DisableItem(FN_INSERT_FIELD); + } + } + break; + + case FN_INSERT_REF_FIELD: + { + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + if ( !pVFrame->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 Allow disabling comment insertion on footnote/endnote for better OOXML interoperability + else if ( rSh.IsCursorInFootnote() && !officecfg::Office::Compatibility::View::AllowCommentsInFootnotes::get() ) + { + 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()->getFieldmarkFor(aCursorPos); + if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMTEXT) + && aCursorPos.nContent.GetIndex() > 0) + { + SwPosition aPos(aCursorPos); + --aPos.nContent; + pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(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(); + sal_uInt16 nType = static_cast(rHlnkItem.GetInsertMode()); + nType &= ~HLINK_HTMLMODE; + const SvxMacroTableDtor* pMacroTable = rHlnkItem.GetMacroTable(); + + SwWrtShell& rSh = GetShell(); + + if( rSh.GetSelectionType() & SelectionType::Text ) + { + rSh.StartAction(); + SfxItemSet aSet(GetPool(), svl::Items{}); + rSh.GetCurAttr( aSet ); + + const SfxPoolItem* pItem; + if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false, &pItem)) + { + // 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(); + 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 000000000..b6aee47f7 --- /dev/null +++ b/sw/source/uibase/shells/textglos.cxx @@ -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 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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(pItem)->GetValue(); + OUString aName; + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem )) + aName = static_cast(pItem)->GetValue(); + OUString aShortName; + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_2, false, &pItem )) + aShortName = static_cast(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(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(pItem)->GetValue(); + OUString aName; + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem )) + aName = static_cast(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 000000000..8247dbdbf --- /dev/null +++ b/sw/source/uibase/shells/textidx.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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* pVFrame = GetView().GetViewFrame(); + + switch( nSlot ) + { + case FN_EDIT_AUTH_ENTRY_DLG : + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwAutoMarkDialog(GetView().GetFrameWeld(), GetShell())); + pDlg->Execute(); + } + break; + case FN_INSERT_AUTH_ENTRY_DLG: + { + // no BASIC support + pVFrame->ToggleChildWindow(FN_INSERT_AUTH_ENTRY_DLG); + Invalidate(rReq.GetSlot()); + } + break; + case FN_INSERT_IDX_ENTRY_DLG: + { + pVFrame->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 pMultDlg(pFact->CreateMultiTOXMarkDlg(GetView().GetFrameWeld(), aMgr)); + nRet = pMultDlg->Execute(); + } + if( nRet == RET_OK) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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: + { + SfxItemSet aSet( + GetPool(), + svl::Items< + 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>{}); + SwWrtShell& rSh = GetShell(); + SwRect aRect; + rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + + 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(static_cast(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 pDlg(pFact->CreateMultiTOXTabDialog( + GetView().GetFrameWeld(), aSet, rSh, const_cast(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* pVFrame = GetView().GetViewFrame(); + SwInsertIdxMarkWrapper *pIdxMrk = static_cast( + pVFrame->GetChildWindow(FN_INSERT_IDX_ENTRY_DLG)); + + SfxChildWindow* pAuthMark = pVFrame->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 ); + 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( rSh.HasSelection() || 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 000000000..85831dc92 --- /dev/null +++ b/sw/source/uibase/shells/textsh.cxx @@ -0,0 +1,1049 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ShellClass_SwTextShell +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SFX_IMPL_INTERFACE(SwTextShell, SwBaseShell) + +IMPL_STATIC_LINK( SwTextShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void ) +{ + 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(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 ) ) + { + 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_ZWNBSP : + 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_ZWNBSP: cIns = CHAR_ZWNBSP; break; + case FN_INSERT_NNBSP: cIns = CHAR_NNBSP; break; + } + rSh.Insert( OUString( cIns ) ); + } + break; + + case FN_INSERT_BREAK: + { + if( !rSh.CursorInsideInputField() ) + { + 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_COLUMN_BREAK: + rSh.InsertColumnBreak(); + rReq.Done(); + break; + + case SID_HYPERLINK_SETLINK: + if (pItem) + InsertHyperlink(*static_cast(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(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(FN_PARAM_1); + const SfxStringItem* pURLItem = rReq.GetArg(FN_PARAM_2); + const SvxSizeItem* pMarginItem = rReq.GetArg(FN_PARAM_3); + const SfxByteItem* pScrollingItem = rReq.GetArg(FN_PARAM_4); + const SfxBoolItem* pBorderItem = rReq.GetArg(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 ); + 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(pScrollingItem->GetValue()); + + Size aMargin; + if ( pMarginItem ) + aMargin = pMarginItem->GetSize(); + + xSet->setPropertyValue("FrameURL", uno::makeAny( pURLItem->GetValue() ) ); + if ( pNameItem ) + xSet->setPropertyValue("FrameName", uno::makeAny( pNameItem->GetValue() ) ); + + if ( eScroll == ScrollingMode::Auto ) + xSet->setPropertyValue("FrameIsAutoScroll", + uno::makeAny( true ) ); + else + xSet->setPropertyValue("FrameIsScrollingMode", + uno::makeAny( eScroll == ScrollingMode::Yes ) ); + + if ( pBorderItem ) + xSet->setPropertyValue("FrameIsBorder", + uno::makeAny( pBorderItem->GetValue() ) ); + + if ( pMarginItem ) + { + xSet->setPropertyValue("FrameMarginWidth", + uno::makeAny( sal_Int32( aMargin.Width() ) ) ); + + xSet->setPropertyValue("FrameMarginHeight", + uno::makeAny( 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(pItem)->GetSize()); + aSize = OutputDevice::LogicToLogic + ( aSize, MapMode( MapUnit::MapTwip ), MapMode( MapUnit::Map100thMM ) ); + + 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) + { + if(FN_INSERT_FRAME_INTERACT_NOCOL != nSlot && + pArgs->GetItemState(SID_ATTR_COLUMNS, false, &pItem) == SfxItemState::SET) + nCols = static_cast(pItem)->GetValue(); + if(pArgs->GetItemState(SID_MODIFIER, false, &pItem) == SfxItemState::SET) + bModifier1 |= KEY_MOD1 == static_cast(pItem)->GetValue(); + } + if(bModifier1 ) + { + SwEditWin& rEdtWin = GetView().GetEditWin(); + Size aWinSize = rEdtWin.GetSizePixel(); + Point aStartPos(aWinSize.Width()/2, aWinSize.Height() / 2); + aStartPos = rEdtWin.PixelToLogic(aStartPos); + aStartPos.AdjustX( -(8 * MM50) ); + aStartPos.AdjustY( -(4 * MM50) ); + Size aSize(16 * MM50, 8 * MM50); + GetShell().LockPaint(); + 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()) ) + { + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + if( HTML_CFG_MSIE == rHtmlOpt.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(static_cast(pItem)->GetValue()); + if(pArgs->GetItemState(FN_PARAM_1, false, &pItem) == SfxItemState::SET) + aPos = static_cast(pItem)->GetValue(); + if(pArgs->GetItemState(FN_PARAM_2, false, &pItem) == SfxItemState::SET) + aSize = static_cast(pItem)->GetSize(); + if(pArgs->GetItemState(SID_ATTR_COLUMNS, false, &pItem) == SfxItemState::SET) + { + const sal_uInt16 nCols = static_cast(pItem)->GetValue(); + if( !bSingleCol && 1 < nCols ) + { + SwFormatCol aFormatCol; + aFormatCol.Init( nCols , (rReq.IsAPI() ? 0 + : DEF_GUTTER_WIDTH), USHRT_MAX ); + aMgr.SetCol(aFormatCol); + } + } + + GetShell().LockPaint(); + GetShell().StartAllAction(); + + aMgr.InsertFlyFrame(eAnchor, aPos, aSize); + + GetShell().EndAllAction(); + GetShell().UnlockPaint(); + } + else + { + SfxItemSet aSet = CreateInsertFrameItemSet(aMgr); + + FieldUnit eMetric = ::GetDfltMetric(dynamic_cast( GetView().GetDocShell()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateFrameTabDialog("FrameDialog", + GetView().GetViewFrame(), + GetView().GetFrameWeld(), + aSet)); + if(pDlg->Execute() == RET_OK && pDlg->GetOutputItemSet()) + { + //local variable necessary at least after call of .AutoCaption() because this could be deleted at this point + SwWrtShell& rShell = GetShell(); + rShell.LockPaint(); + rShell.StartAllAction(); + rShell.StartUndo(SwUndoId::INSERT); + + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + aMgr.SetAttrSet(*pOutSet); + + // At first delete the selection at the ClickToEditField. + if( rShell.IsInClickToEdit() ) + rShell.DelRight(); + + aMgr.InsertFlyFrame(); + + uno::Reference< frame::XDispatchRecorder > xRecorder = + GetView().GetViewFrame()->GetBindings().GetRecorder(); + if ( xRecorder.is() ) + { + //FN_INSERT_FRAME + sal_uInt16 nAnchor = static_cast(aMgr.GetAnchor()); + rReq.AppendItem(SfxUInt16Item(nSlot, nAnchor)); + rReq.AppendItem(SfxPointItem(FN_PARAM_1, rShell.GetObjAbsPos())); + rReq.AppendItem(SvxSizeItem(FN_PARAM_2, rShell.GetObjSize())); + rReq.Done(); + } + + GetView().AutoCaption(FRAME_CAP); + + { + SwRewriter aRewriter; + + aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME)); + + rShell.EndUndo(SwUndoId::INSERT, &aRewriter); + } + rShell.EndAllAction(); + rShell.UnlockPaint(); + } + } + break; + } + case FN_FORMAT_COLUMN : + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + VclPtr 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(); + + bool bCursorInHidden = false; + if( !rSh.HasMark() ) + { + rSh.Push(); + bCursorInHidden = rSh.SelectHiddenRange(); + rSh.Pop(); + } + + 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) + { + SvxHtmlOptions& rHtmlOpt = SvxHtmlOptions::Get(); + const sal_uInt16 nExport = rHtmlOpt.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: + { + SfxItemSet aSet(GetPool(), svl::Items{}); + rSh.GetCurAttr( aSet ); + + SvxHyperlinkItem aHLinkItem; + const SfxPoolItem* pItem; + if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false, &pItem)) + { + const SwFormatINetFormat* pINetFormat = static_cast(pItem); + 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(255, sReturn.getLength())); + aHLinkItem.SetName(comphelper::string::stripEnd(sReturn, ' ')); + } + + aHLinkItem.SetInsertMode(static_cast(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) +{ + static const sal_uInt16 aFrameAttrRange[] = + { + RES_FRMATR_BEGIN, RES_FRMATR_END-1, + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER, + FN_GET_PRINT_AREA, FN_GET_PRINT_AREA, + SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE, + FN_SET_FRM_NAME, FN_SET_FRM_NAME, + SID_HTML_MODE, SID_HTML_MODE, + SID_COLOR_TABLE, SID_PATTERN_LIST, + XATTR_FILL_FIRST, XATTR_FILL_LAST, // tdf#95003 + 0 + }; + + SfxItemSet aSet(GetPool(), aFrameAttrRange ); + 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); + + return aSet; +} + +void SwTextShell::InsertSymbol( SfxRequest& rReq ) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = nullptr; + if( pArgs ) + pArgs->GetItemState(GetPool().GetWhich(SID_CHARMAP), false, &pItem); + + OUString aChars, aFontName; + if ( pItem ) + { + aChars = static_cast(pItem)->GetValue(); + const SfxPoolItem* pFtItem = nullptr; + pArgs->GetItemState( GetPool().GetWhich(SID_ATTR_SPECIALCHAR), false, &pFtItem); + const SfxStringItem* pFontItem = dynamic_cast( pFtItem ); + if ( pFontItem ) + aFontName = pFontItem->GetValue(); + } + + SwWrtShell &rSh = GetShell(); + SfxItemSet aSet( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aSet ); + SvtScriptType nScript = rSh.GetScriptType(); + + std::shared_ptr aFont(std::make_shared(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(pI->Clone())); + } + else + { + aFont.reset(static_cast( + aSet.Get( + GetWhichOfScript( + RES_CHRATR_FONT, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) )).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 pDlg(pFact->CreateCharMapDialog(GetView().GetFrameWeld(), aAllSet, xFrame)); + pDlg->Execute(); + return; + } + + if( !aChars.isEmpty() ) + { + 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(pI->Clone())); + } + else + { + aFont.reset(static_cast(aSet.Get( GetWhichOfScript( + RES_CHRATR_FONT, + SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetAppLanguage() ) )).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 aNewFontItem(aFont->Clone()); + aNewFontItem->SetFamilyName( aNewFont.GetFamilyName() ); + aNewFontItem->SetFamily( aNewFont.GetFamilyType()); + aNewFontItem->SetPitch( aNewFont.GetPitch()); + aNewFontItem->SetCharSet( aNewFont.GetCharSet() ); + + SfxItemSet aRestoreSet( GetPool(), svl::Items{} ); + + 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( GetPool().GetWhich(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 000000000..4342ed713 --- /dev/null +++ b/sw/source/uibase/shells/textsh1.cxx @@ -0,0 +1,2179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 const & pCoreSet, bool bSel, bool bSelectionPut, SfxRequest *pReq); + +static void sw_CharDialog(SwWrtShell &rWrtSh, bool bUseDialog, sal_uInt16 nSlot, const SfxItemSet *pArgs, SfxRequest *pReq ) +{ + FieldUnit eMetric = ::GetDfltMetric(dynamic_cast( &rWrtSh.GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + auto pCoreSet = std::make_shared( + rWrtSh.GetView().GetPool(), + svl::Items< + RES_CHRATR_BEGIN, RES_CHRATR_END - 1, + RES_TXTATR_INETFMT, RES_TXTATR_INETFMT, + RES_BACKGROUND, RES_SHADOW, + XATTR_FILLSTYLE, XATTR_FILLCOLOR, + 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.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 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_FOR_PARAGRAPH) + pDlg->SetCurPageId("font"); + else if (pReq) + { + const SfxStringItem* pItem = (*pReq).GetArg(FN_PARAM_1); + if (pItem) + pDlg->SetCurPageId(OUStringToOString(pItem->GetValue(), RTL_TEXTENCODING_UTF8)); + } + } + + if (bUseDialog) + { + std::shared_ptr pRequest; + if (pReq) + { + pRequest = std::make_shared(*pReq); + pReq->Ignore(); // the 'old' request is not relevant any more + } + pDlg->StartExecuteAsync([pDlg, &rWrtSh, pCoreSet, bSel, bSelectionPut, pRequest](sal_Int32 nResult){ + if (nResult == RET_OK) + { + sw_CharDialogResult(pDlg->GetOutputItemSet(), rWrtSh, pCoreSet, bSel, bSelectionPut, pRequest.get()); + } + pDlg->disposeOnce(); + }); + } + else if (pArgs) + { + sw_CharDialogResult(pArgs, rWrtSh, pCoreSet, bSel, bSelectionPut, pReq); + } +} + +static void sw_CharDialogResult(const SfxItemSet* pSet, SwWrtShell &rWrtSh, std::shared_ptr const & pCoreSet, bool bSel, bool bSelectionPut, SfxRequest *pReq) +{ + SfxItemSet aTmpSet( *pSet ); + ::ConvertAttrGenToChar(aTmpSet, *pCoreSet); + + const SfxPoolItem* pSelectionItem; + bool bInsert = false; + sal_Int32 nInsert = 0; + + // The old item is for unknown reasons back in the set again. + if( !bSelectionPut && SfxItemState::SET == aTmpSet.GetItemState(FN_PARAM_SELECTION, false, &pSelectionItem) ) + { + OUString sInsert = static_cast(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->IsAutoUpdateFormat()) + { + 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(); + } + +} + +static short lcl_AskRedlineFlags(weld::Window *pWin) +{ + std::unique_ptr xBuilder(Application::CreateBuilder(pWin, "modules/swriter/ui/queryredlinedialog.ui")); + std::unique_ptr xQBox(xBuilder->weld_message_dialog("QueryRedlineDialog")); + return xQBox->run(); +} + +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(); + const SfxPoolItem* pItem = nullptr; + if ( SfxItemState::SET == pSet->GetItemState(FN_DROP_TEXT, false, &pItem) ) + { + if ( !static_cast(pItem)->GetValue().isEmpty() ) + rWrtSh.ReplaceDropText(static_cast(pItem)->GetValue(), pPaM); + } + rWrtSh.SetAttrSet(*pSet, SetAttrMode::DEFAULT, pPaM); + rWrtSh.EndAction(); + SwTextFormatColl* pColl = rWrtSh.GetPaMTextFormatColl(pPaM); + if(pColl && pColl->IsAutoUpdateFormat()) + { + 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(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 = static_cast(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(static_cast(pSet->Get(FN_NUMBER_NEWSTART_AT)).GetValue()); + rWrtSh.SetNumRuleStart(false, pPaM); + } + // #i56253# + if ( bUndoNeeded ) + { + rWrtSh.EndUndo( SwUndoId::INSATTR ); + } +} + +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: + { + long nMaxUnits = 256; + sal_Int32 nSelLength = rWrtSh.GetSelText().getLength(); + if( rWrtSh.IsSelection() && !rWrtSh.IsMultiSelection() && (nSelLength < nMaxUnits) ) + nMaxUnits = nSelLength; + + 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 + auto xInfo(std::make_unique( + rWrtSh.GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", + "InfoReadonlyDialog")); + xInfo->run(); + 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(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 *pViewFrame = GetView().GetViewFrame(); + + if (aNewLangText == "*") + { + // open the dialog "Tools/Options/Language Settings - Language" + // to set the documents default language + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ScopedVclPtr 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()) + { + const OUString aSelectionLangPrefix("Current_"); + const OUString aParagraphLangPrefix("Paragraph_"); + const OUString aDocumentLangPrefix("Default_"); + const OUString aStrNone("LANGUAGE_NONE"); + const OUString aStrResetLangs("RESET_LANGUAGES"); + + SfxItemSet aCoreSet( GetPool(), + svl::Items{} ); + + 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(), ""); + bForSelection = true; + } + else if (-1 != (nPos = aNewLangText.indexOf(aParagraphLangPrefix))) + { + // ... for the current paragraph language + aNewLangText = aNewLangText.replaceAt(nPos, aParagraphLangPrefix.getLength(), ""); + bForSelection = true; + bForParagraph = true; + } + else if (-1 != (nPos = aNewLangText.indexOf(aDocumentLangPrefix))) + { + // ... as default document language + aNewLangText = aNewLangText.replaceAt(nPos, aDocumentLangPrefix.getLength(), ""); + 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 == aStrNone) + SwLangHelper::SetLanguage_None( rWrtSh, bForSelection, aCoreSet ); + else if (aNewLangText == aStrResetLangs) + 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 + pViewFrame->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(SID_THES); + 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(FN_PARAM_1); + const SfxStringItem* pNameItem = rReq.GetArg(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( CRSR_SKIP_CHARS, true, 1, false ); + SfxItemSet aSet( rWrtSh.GetAttrPool(), svl::Items{} ); + 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 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) + std::set aAttribs; + + sal_uInt16 aResetableSetRange[] = { + RES_FRMATR_BEGIN, 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_TXTATR_UNKNOWN_CONTAINER, RES_TXTATR_UNKNOWN_CONTAINER, + RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, + 0 + }; + const sal_uInt16 *pUShorts = aResetableSetRange; + while (*pUShorts) + { + for (sal_uInt16 i = pUShorts[0]; i <= pUShorts[1]; ++i) + aAttribs.insert( aAttribs.end(), i ); + pUShorts += 2; + } + // we don't want to change writing direction. + aAttribs.erase( RES_FRAMEDIR ); + rWrtSh.ResetAttr( aAttribs ); + + // also clear the direct formatting flag inside SwTableBox(es) + GetView().GetDocShell()->GetFEShell()->UpdateTableStyleFormatting(nullptr, true); + + rReq.Done(); + break; + } + case FN_INSERT_BREAK_DLG: + { + sal_uInt16 nKind=0; + ::std::optional oPageNumber; + OUString aTemplateName; + if ( pItem ) + { + nKind = static_cast(pItem)->GetValue(); + const SfxStringItem* pTemplate = rReq.GetArg(FN_PARAM_1); + const SfxUInt16Item* pNumber = rReq.GetArg(FN_PARAM_2); + const SfxBoolItem* pIsNumberFilled = rReq.GetArg(FN_PARAM_3); + if ( pTemplate ) + aTemplateName = pTemplate->GetValue(); + if ( pNumber && pIsNumberFilled && pIsNumberFilled->GetValue() ) + oPageNumber = pNumber->GetValue(); + } + else + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwBreakDlg(GetView().GetFrameWeld(), rWrtSh)); + if ( pDlg->Execute() == RET_OK ) + { + nKind = pDlg->GetKind(); + aTemplateName = pDlg->GetTemplateName(); + oPageNumber = pDlg->GetPageNumber(); + + bool bIsNumberFilled = false; + sal_uInt16 nPageNumber = 0; + + if (oPageNumber) + { + bIsNumberFilled = true; + nPageNumber = *oPageNumber; + } + + rReq.AppendItem( SfxInt16Item ( FN_INSERT_BREAK_DLG, nKind ) ); + rReq.AppendItem( SfxStringItem( FN_PARAM_1, aTemplateName ) ); + rReq.AppendItem( SfxUInt16Item( FN_PARAM_2, nPageNumber ) ); + rReq.AppendItem( SfxBoolItem ( FN_PARAM_3, bIsNumberFilled ) ); + rReq.Done(); + } + else + rReq.Ignore(); + } + + switch ( nKind ) + { + case 1 : + rWrtSh.InsertLineBreak(); break; + case 2 : + rWrtSh.InsertColumnBreak(); break; + case 3 : + { + rWrtSh.StartAllAction(); + if( !aTemplateName.isEmpty() ) + rWrtSh.InsertPageBreak( &aTemplateName, oPageNumber ); + else + rWrtSh.InsertPageBreak(); + rWrtSh.EndAllAction(); + } + } + + break; + } + case FN_INSERT_BOOKMARK: + { + if ( pItem ) + { + OUString sName = static_cast(pItem)->GetValue(); + rWrtSh.SetBookmark( vcl::KeyCode(), sName ); + } + else + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwInsertBookmarkDlg(GetView().GetFrameWeld(), rWrtSh, rReq)); + pDlg->Execute(); + } + + break; + } + case FN_DELETE_BOOKMARK: + { + if (pItem && !rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS)) + { + IDocumentMarkAccess* const pMarkAccess = rWrtSh.getIDocumentMarkAccess(); + pMarkAccess->deleteMark( pMarkAccess->findMark(static_cast(pItem)->GetValue()) ); + } + 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])); + + 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 ); + aFlags.bWithRedlining = false; + + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + if (pVFrame->HasChildWindow(FN_REDLINE_ACCEPT)) + pVFrame->ToggleChildWindow(FN_REDLINE_ACCEPT); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr xDlg(pFact->CreateSwModalRedlineAcceptDlg(GetView().GetEditWin().GetFrameWeld())); + + switch (lcl_AskRedlineFlags(GetView().GetFrameWeld())) + { + case RET_OK: + { + xDlg->AcceptAll(true); + SfxRequest aReq( pVFrame, FN_AUTOFORMAT_APPLY ); + aReq.Done(); + rReq.Ignore(); + break; + } + + case RET_CANCEL: + xDlg->AcceptAll(false); + rReq.Ignore(); + break; + + case 102: + xDlg->Execute(); + rReq.Done(); + break; + } + } + 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 ); + rReq.Done(); + } + break; + case FN_AUTOFORMAT_AUTO: + { + SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); + bool bSet = pItem ? static_cast(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 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 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(pField)->GetSetRefName(), + static_cast(pField)->GetSubType(), + static_cast(pField)->GetSeqNo() ); + rWrtSh.EndAllAction(); + rReq.Done(); + } + } + break; + case FN_EDIT_FORMULA: + { + const sal_uInt16 nId = SwInputChild::GetChildWindowId(); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + if(pItem) + { + //if the ChildWindow is active it has to be removed + if( pVFrame->HasChildWindow( nId ) ) + { + pVFrame->ToggleChildWindow( nId ); + pVFrame->GetBindings().InvalidateAll( true ); + } + + OUString sFormula(static_cast(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() ) + { + SfxItemSet aSet( rWrtSh.GetAttrPool(), svl::Items{} ); + 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(); + pVFrame->ToggleChildWindow( nId ); + if( !pVFrame->HasChildWindow( nId ) ) + pVFrame->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 + std::set aAttribs; + aAttribs.insert( RES_TXTATR_INETFMT ); + rWrtSh.ResetAttr( aAttribs ); + 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: + { + sw_CharDialog( rWrtSh, bUseDialog, nSlot, pArgs, &rReq ); + } + break; + case SID_CHAR_DLG_FOR_PARAGRAPH: + { + rWrtSh.Push(); //save current cursor + SwLangHelper::SelectCurrentPara( rWrtSh ); + sw_CharDialog( rWrtSh, bUseDialog, nSlot, pArgs, &rReq ); + rWrtSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // restore old cursor + } + 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 SfxPoolItem* pPaMItem = nullptr; + pArgs->GetItemState( GetPool().GetWhich( FN_PARAM_PAM ), false, &pPaMItem ); + if ( pPaMItem ) + pPaM = static_cast< const SwPaMItem* >( pPaMItem )->GetValue( ); + } + + if ( !pPaM ) + pPaM = rWrtSh.GetCursor(); + + FieldUnit eMetric = ::GetDfltMetric( dynamic_cast( &GetView()) != nullptr ); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + + bool bApplyCharUnit = ::HasCharUnit( dynamic_cast( &GetView()) != nullptr ); + SW_MOD()->PutItem(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, bApplyCharUnit)); + + SfxItemSet aCoreSet( + GetPool(), + svl::Items< + 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>{}); + + // 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 + const 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 = static_cast(::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 long nOff = rWrtSh.getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT) ? + aCoreSet.Get( RES_LR_SPACE ).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 pDlg; + + if ( bUseDialog && GetActiveView() ) + { + OString sDefPage; + if (pItem) + sDefPage = OUStringToOString(static_cast(pItem)->GetValue(), RTL_TEXTENCODING_UTF8); + + 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(pArgs->Get(nSlot))); + aParaMargin.SetWhich( RES_LR_SPACE); + aCoreSet.Put(aParaMargin); + + sw_ParagraphDialogResult(&aCoreSet, rWrtSh, rReq, pPaM); + } + else + sw_ParagraphDialogResult(const_cast(pArgs), rWrtSh, rReq, pPaM); + } + else if (pDlg) + { + auto pRequest = std::make_shared(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + + auto xPaM(std::make_shared(*pPaM, nullptr)); // tdf#134439 make a copy to use at later apply + pDlg->StartExecuteAsync([pDlg, &rWrtSh, pRequest, nDefDist, xPaM](sal_Int32 nResult){ + if (nResult == RET_OK) + { + // Apply defaults if necessary. + SfxItemSet* pSet = const_cast(pDlg->GetOutputItemSet()); + sal_uInt16 nNewDist; + const SfxPoolItem* pItem2 = nullptr; + if (SfxItemState::SET == pSet->GetItemState(SID_ATTR_TABSTOP_DEFAULTS, false, &pItem2) && + nDefDist != (nNewDist = static_cast(pItem2)->GetValue()) ) + { + SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP ); + MakeDefTabs( nNewDist, aDefTabs ); + rWrtSh.SetDefault( aDefTabs ); + pSet->ClearItem( SID_ATTR_TABSTOP_DEFAULTS ); + } + + if (SfxItemState::SET == pSet->GetItemState(FN_PARAM_1, false, &pItem2)) + { + pSet->Put(SfxStringItem(FN_DROP_TEXT, static_cast(pItem2)->GetValue())); + pSet->ClearItem(FN_PARAM_1); + } + + if (SfxItemState::SET == pSet->GetItemState(RES_PARATR_DROP, false, &pItem2)) + { + OUString sCharStyleName; + if (static_cast(pItem2)->GetCharFormat()) + sCharStyleName = static_cast(pItem2)->GetCharFormat()->GetName(); + pSet->Put(SfxStringItem(FN_DROP_CHAR_STYLE_NAME, sCharStyleName)); + } + + sw_ParagraphDialogResult(pSet, rWrtSh, *pRequest, xPaM.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: + { + Color aSet; + OUString sColor; + const SfxPoolItem* pColorStringItem = nullptr; + bool bHasItem = false; + + if(pItem) + { + aSet = static_cast(pItem)->GetValue(); + bHasItem = true; + } + else if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_COLOR_STR, false, &pColorStringItem)) + { + sColor = static_cast(pColorStringItem)->GetValue(); + aSet = Color(sColor.toInt32(16)); + bHasItem = true; + } + + if (bHasItem) + { + SwEditWin& rEditWin = GetView().GetEditWin(); + rEditWin.SetWaterCanTextColor(aSet); + 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 (aSet, RES_CHRATR_COLOR)); + } + + rReq.Done(); + } + } + break; + case SID_ATTR_CHAR_COLOR_BACKGROUND: + case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT: + case SID_ATTR_CHAR_COLOR_EXT: + { + Color aSet; + OUString sColor; + const SfxPoolItem* pColorStringItem = nullptr; + + if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_COLOR_STR, false, &pColorStringItem)) + { + sColor = static_cast(pColorStringItem)->GetValue(); + if (sColor == "transparent") + aSet = COL_TRANSPARENT; + else + aSet = Color(sColor.toInt32(16)); + } + else if (pItem) + aSet = static_cast(pItem)->GetValue(); + else + aSet = COL_TRANSPARENT; + + SwEditWin& rEdtWin = GetView().GetEditWin(); + if (nSlot != SID_ATTR_CHAR_COLOR_EXT) + rEdtWin.SetWaterCanTextBackColor(aSet); + else if (pItem) + rEdtWin.SetWaterCanTextColor(aSet); + + SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate(); + SwApplyTemplate aTempl; + if (!pApply && (rWrtSh.HasSelection() || rReq.IsAPI())) + { + if (nSlot != SID_ATTR_CHAR_COLOR_EXT) + { + SfxItemSet aCoreSet( rWrtSh.GetView().GetPool(), svl::Items< + RES_CHRATR_BACKGROUND, RES_CHRATR_BACKGROUND>{} ); + + rWrtSh.GetCurAttr( aCoreSet ); + + // Remove highlight if already set of the same color + const SvxBrushItem& rBrushItem = aCoreSet.Get(RES_CHRATR_BACKGROUND); + if ( aSet == rBrushItem.GetColor() ) + aSet = COL_TRANSPARENT; + + ApplyCharBackground(aSet, rWrtSh); + } + else + rWrtSh.SetAttrItem( + SvxColorItem(aSet, RES_CHRATR_COLOR) ); + } + else if (nSlot == SID_ATTR_CHAR_COLOR_BACKGROUND) + { + if (!pApply || pApply->nColor != SID_ATTR_CHAR_COLOR_BACKGROUND_EXT) + { + aTempl.nColor = SID_ATTR_CHAR_COLOR_BACKGROUND_EXT; + rEdtWin.SetApplyTemplate(aTempl); + } + } + 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(-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(pItem)->GetValue(); + bool bOn = true; + if( SfxItemState::SET == pArgs->GetItemState(FN_PARAM_1, false, &pItem)) + bOn = static_cast(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(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: + { + SfxItemSet aSet(GetPool(), + svl::Items{}); + rWrtSh.GetCurAttr(aSet); + if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT )) + { + const SwFormatINetFormat& rINetFormat = dynamic_cast( aSet.Get(RES_TXTATR_INETFMT) ); + if( nSlot == SID_COPY_HYPERLINK_LOCATION ) + { + ::uno::Reference< datatransfer::clipboard::XClipboard > xClipboard = GetView().GetEditWin().GetClipboard(); + vcl::unohelper::TextDataObject::CopyStringTo( + rINetFormat.GetValue(), + xClipboard ); + } + else + rWrtSh.ClickToINetAttr(rINetFormat); + } + } + 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* pViewFrame = GetView().GetViewFrame(); + pViewFrame->GetBindings().Invalidate(nSlot); + pViewFrame->GetBindings().Update(nSlot); + } + break; + case SID_FM_CTL_PROPERTIES: + { + SwPosition aPos(*GetShell().GetCursor()->GetPoint()); + sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(aPos); + if ( !pFieldBM ) + { + --aPos.nContent; + pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(aPos); + } + + if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateDropDownFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM)); + if (pDlg->Execute() == RET_OK) + { + pFieldBM->Invalidate(); + rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() ); + rWrtSh.UpdateCursor(); // cursor position might be invalid + // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen + dynamic_cast<::sw::mark::DropDownFieldmark&>(*pFieldBM).HideButton(); + } + } + else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + sw::mark::DateFieldmark& rDateField = dynamic_cast(*pFieldBM); + ScopedVclPtr pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), &rDateField, GetView().GetDocShell()->GetDoc())); + if (pDlg->Execute() == RET_OK) + { + rDateField.Invalidate(); + rWrtSh.InvalidateWindows( rWrtSh.GetView().GetVisArea() ); + rWrtSh.UpdateCursor(); // cursor position might be invalid + // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen + rDateField.HideButton(); + } + } + 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_SPELLCHECK_IGNORE: + { + SwPaM *pPaM = rWrtSh.GetCursor(); + if (pPaM) + SwEditShell::IgnoreGrammarErrorAt( *pPaM ); + } + break; + case SID_SPELLCHECK_IGNORE_ALL: + { + OUString sApplyText; + const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_1); + if (pItem2) + sApplyText = pItem2->GetValue(); + + const OUString sGrammarType("Grammar"); + const OUString sSpellingType("Spelling"); + + if(sApplyText == sGrammarType) + { + 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 ); + // 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 == sSpellingType) + { + SwRect aToFill; + uno::Reference< linguistic2::XSpellAlternatives > xSpellAlt( rWrtSh.GetCorrection(nullptr, aToFill) ); + 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->getEntry(sWord).is()) + { + SvxDicError(rWrtSh.GetView().GetFrameWeld(), nAddRes); + } + } + } + break; + case SID_SPELLCHECK_APPLY_SUGGESTION: + { + OUString sApplyText; + const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_1); + if (pItem2) + sApplyText = pItem2->GetValue(); + + const OUString sSpellingRule("Spelling_"); + const OUString sGrammarRule("Grammar_"); + + bool bGrammar = false; + sal_Int32 nPos = 0; + uno::Reference< linguistic2::XSpellAlternatives > xSpellAlt; + if(-1 != (nPos = sApplyText.indexOf( sGrammarRule ))) + { + sApplyText = sApplyText.replaceAt(nPos, sGrammarRule.getLength(), ""); + bGrammar = true; + } + else if (-1 != (nPos = sApplyText.indexOf( sSpellingRule ))) + { + sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), ""); + 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()); + 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(); + + rWrtSh.Replace(aTmp, false); + + 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 ) + { + switch ( nWhich ) + { + 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(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( 4 ); + aSeq[0] = aCurrentLang; + aSeq[1] = aScriptTypesInUse; + aSeq[2] = aKeyboardLang; + aSeq[3] = 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_EMOJI_CONTROL: + 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; + if ( rSh.GetFrameType(nullptr,true) & nNoType ) + 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_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(), nWhich) ); + } + else + { + const SvxBrushItem& aBrushItem2 = aSet.Get(RES_CHRATR_BACKGROUND); + rSet.Put( SvxColorItem(aBrushItem2.GetColor(), nWhich) ); + } + } + break; + case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT: + 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() ) + { + 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 aList; + const OUString sPhysical("IsPhysical"); + const OUString sDisplay("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 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: + { + SvtCJKOptions aCJKOptions; + if( !aCJKOptions.IsRubyEnabled() + || rSh.CursorInsideInputField() ) + { + GetView().GetViewFrame()->GetBindings().SetVisibleState( nWhich, false ); + rSet.DisableItem(nWhich); + } + else + GetView().GetViewFrame()->GetBindings().SetVisibleState( nWhich, true ); + } + 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: + case SID_COPY_HYPERLINK_LOCATION: + { + SfxItemSet aSet(GetPool(), + svl::Items{}); + rSh.GetCurAttr(aSet); + if(SfxItemState::SET > aSet.GetItemState( RES_TXTATR_INETFMT ) || rSh.HasReadonlySel()) + { + rSet.DisableItem(nWhich); + } + } + break; + case SID_REMOVE_HYPERLINK: + { + SfxItemSet aSet(GetPool(), + svl::Items{}); + 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: + { + SvtCJKOptions aCJKOptions; + if(!aCJKOptions.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_OPEN_HYPERLINK: + { + SfxItemSet aSet(GetPool(), + svl::Items{}); + rSh.GetCurAttr(aSet); + if(SfxItemState::SET > aSet.GetItemState( RES_TXTATR_INETFMT, false )) + rSet.DisableItem(nWhich); + } + break; + case SID_OPEN_SMARTTAGMENU: + { + std::vector< OUString > aSmartTagTypes; + uno::Sequence< uno::Reference< container::XStringKeyMap > > aStringKeyMaps; + uno::Reference 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 xController = GetView().GetController(); + const lang::Locale aLocale( SW_BREAKITER()->GetLocale( GetAppLanguageTag() ) ); + const OUString& aApplicationName( rSmartTagMgr.GetApplicationName() ); + const OUString aRangeText = xRange->getString(); + + const SvxSmartTagItem aItem( nWhich, + aActionComponentsSequence, + aActionIndicesSequence, + aStringKeyMaps, + xRange, + xController, + 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_BUL_NUM_RULE_INDEX: + case FN_NUM_NUM_RULE_INDEX: + case FN_OUTLINE_RULE_INDEX: + { + SwNumRule* pCurRule = const_cast(GetShell().GetNumRuleAtCurrCursorPos()); + sal_uInt16 nActNumLvl = USHRT_MAX; + if( pCurRule ) + { + nActNumLvl = GetShell().GetNumLevel(); + if( nActNumLvl < MAXLEVEL ) + { + nActNumLvl = 1<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 : + { + SvtCTLOptions aCTLOptions; + bool bEnabled = aCTLOptions.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 + SfxItemSet aSet(GetShell().GetAttrPool(), svl::Items{}); + 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()->getFieldmarkFor(aPos); + if ( !pFieldBM && aPos.nContent.GetIndex() > 0) + { + --aPos.nContent; + pFieldBM = GetShell().getIDocumentMarkAccess()->getFieldmarkFor(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; + } + 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 000000000..0438d42aa --- /dev/null +++ b/sw/source/uibase/shells/textsh2.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +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 aSelection; + Reference xCursor; + Reference xConnection; +}; + +void SwTextShell::ExecDB(SfxRequest const &rReq) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + SwDBManager* pDBManager = GetShell().GetDBManager(); + OUString sSourceArg, sCommandArg; + sal_Int32 nCommandTypeArg = 0; + + const SfxPoolItem* pSourceItem = nullptr; + const SfxPoolItem* pCursorItem = nullptr; + const SfxPoolItem* pConnectionItem = nullptr; + const SfxPoolItem* pCommandItem = nullptr; + const SfxPoolItem* pCommandTypeItem = nullptr; + const SfxPoolItem* pSelectionItem = nullptr; + + // first get the selection of rows to be inserted + pArgs->GetItemState(FN_DB_DATA_SELECTION_ANY, false, &pSelectionItem); + + Sequence aSelection; + if(pSelectionItem) + static_cast(pSelectionItem)->GetValue() >>= aSelection; + + // get the data source name + pArgs->GetItemState(FN_DB_DATA_SOURCE_ANY, false, &pSourceItem); + if(pSourceItem) + static_cast(pSourceItem)->GetValue() >>= sSourceArg; + + // get the command + pArgs->GetItemState(FN_DB_DATA_COMMAND_ANY, false, &pCommandItem); + if(pCommandItem) + static_cast(pCommandItem)->GetValue() >>= sCommandArg; + + // get the command type + pArgs->GetItemState(FN_DB_DATA_COMMAND_TYPE_ANY, false, &pCommandTypeItem); + if(pCommandTypeItem) + static_cast(pCommandTypeItem)->GetValue() >>= nCommandTypeArg; + + Reference xConnection; + pArgs->GetItemState(FN_DB_CONNECTION_ANY, false, &pConnectionItem); + if ( pConnectionItem ) + static_cast(pConnectionItem)->GetValue() >>= xConnection; + // may be we even get no connection + if ( !xConnection.is() ) + { + Reference 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 xCursor; + pArgs->GetItemState(FN_DB_DATA_CURSOR_ANY, false, &pCursorItem); + if ( pCursorItem ) + static_cast(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 SfxPoolItem* pColumnItem = nullptr; + const SfxPoolItem* pColumnNameItem = nullptr; + + pArgs->GetItemState(FN_DB_COLUMN_ANY, false, &pColumnItem); + pArgs->GetItemState(FN_DB_DATA_COLUMN_NAME_ANY, false, &pColumnNameItem); + + OUString sColumnName; + if(pColumnNameItem) + static_cast(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 = static_cast(pConnectionItem)->GetValue(); + if(pColumnItem) + aData.m_aDBColumn = static_cast(pColumnItem)->GetValue(); + aFieldMgr.InsertField(aData); + SfxViewFrame* pViewFrame = GetView().GetViewFrame(); + uno::Reference< XDispatchRecorder > xRecorder = + pViewFrame->GetBindings().GetRecorder(); + if ( xRecorder.is() ) + { + SfxRequest aReq( pViewFrame, FN_INSERT_DBFIELD ); + aReq.AppendItem( SfxUInt16Item(FN_PARAM_FIELD_TYPE, static_cast(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(p); + if( pDBStruct ) + { + bool bDispose = false; + Reference< sdbc::XConnection> xConnection = pDBStruct->xConnection; + Reference 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(); + ScopedVclPtrpDlg (pFact->CreateSwInsertDBColAutoPilot(GetView(), + xSource, + xColSupp, + aDBData)); + if( RET_OK == pDlg->Execute() ) + { + Reference xResSet = pDBStruct->xCursor; + pDlg->DataToDoc( pDBStruct->aSelection, xSource, xConnection, xResSet); + } + } + if ( bDispose ) + ::comphelper::disposeComponent(xConnection); + } + + delete pDBStruct; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/shells/txtattr.cxx b/sw/source/uibase/shells/txtattr.cxx new file mode 100644 index 000000000..839e7f760 --- /dev/null +++ b/sw/source/uibase/shells/txtattr.cxx @@ -0,0 +1,845 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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( pArgs-> + Get( nWhich )).GetValue() ? STATE_ON : STATE_OFF; + } + + SfxItemSet aSet( GetPool(), svl::Items{} ); + 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 ); + if(eEscape == SvxEscapement::Superscript) + aEscape.GetEsc() = DFLT_ESC_AUTO_SUPER; + else if(eEscape == SvxEscapement::Subscript) + aEscape.GetEsc() = DFLT_ESC_AUTO_SUB; + 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->IsAutoUpdateFormat() ) + 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(rItem) ); + if ( USHRT_MAX == aINetFormat.GetVisitedFormatId() ) + { + OSL_ENSURE( false, " - 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, " - 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( + aSetItem.GetItemOfScript( nScriptTypes ) ) ); + std::vector >> 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( *(pPaM->GetMark()), *(pPaM->GetPoint())) ); + } + else + vItems = rWrtSh.GetItemWithPaM( RES_CHRATR_FONTSIZE ); + + rWrtSh.StartUndo( SwUndoId::INSATTR ); + for( std::pair< const SfxPoolItem*, std::unique_ptr >& iPair : vItems ) + { + std::unique_ptr 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( 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!! + SfxItemSet aSet( GetPool(), + svl::Items{} ); + + 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( 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_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 : + { + SfxItemSet aAdjustSet( GetPool(), + svl::Items{} ); + 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->IsAutoUpdateFormat()) + { + 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(pItem)->GetValue(); + SfxItemSet aSet(GetPool(), svl::Items{}); + 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 + { + SfxItemSet aSet(GetPool(), svl::Items{}); + rSh.GetCurAttr(aSet); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwDropCapsDialog(GetView().GetFrameWeld(), aSet)); + if (pDlg->Execute() == RET_OK) + { + rSh.StartAction(); + rSh.StartUndo( SwUndoId::START ); + if ( SfxItemState::SET == aSet.GetItemState(HINT_END,false,&pItem) ) + { + if ( !static_cast(pItem)->GetValue().isEmpty() ) + rSh.ReplaceDropText(static_cast(pItem)->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) + { + SfxItemSet aCoreSet( GetPool(), + svl::Items{}); + 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( 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(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(pItem)->GetLineSpaceRule() == SvxLineSpaceRule::Auto ) + { + if(SvxInterLineSpaceRule::Off == + static_cast(pItem)->GetInterLineSpaceRule()) + nLineSpace = 100; + else + nLineSpace = static_cast(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(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_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( + 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 >> + vFontHeight = rSh.GetItemWithPaM( RES_CHRATR_FONTSIZE ); + for ( const std::pair< const SfxPoolItem*, std::unique_ptr>& aIt : vFontHeight ) + { + if (!aIt.first) + { + rSet.DisableItem(FN_GROW_FONT_SIZE); + rSet.DisableItem(FN_SHRINK_FONT_SIZE); + break; + } + pSize = static_cast( 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_LR_SPACE); + if( eState >= SfxItemState::DEFAULT ) + { + SvxLRSpaceItem aLR = aCoreSet.Get( RES_LR_SPACE ); + 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 ( !SW_MOD()->GetCTLOptions().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: + { +#if OSL_DEBUG_LEVEL > 1 + const SfxPoolItem& rItem = aCoreSet.Get(GetPool().GetWhich(nSlot), true); + rSet.Put(rItem); +#else + rSet.Put(aCoreSet.Get( GetPool().GetWhich(nSlot))); +#endif + nSlot = 0; + } + break; + case SID_ATTR_PARA_MODEL: + { + SfxItemSet aTemp(GetPool(), + svl::Items{}); + aTemp.Put(aCoreSet); + ::SwToSfxPageDescAttr(aTemp); + rSet.Put(aTemp.Get(SID_ATTR_PARA_MODEL)); + nSlot = 0; + } + break; + case RES_TXTATR_INETFMT: + { + SfxItemSet aSet(GetPool(), svl::Items{}); + 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 000000000..4ca50d6da --- /dev/null +++ b/sw/source/uibase/shells/txtcrsr.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +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) + { + const SfxPoolItem *pItem; + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_MOVE_COUNT, true, &pItem)) + nCount = static_cast(pItem)->GetValue(); + if(SfxItemState::SET == pArgs->GetItemState(FN_PARAM_MOVE_SELECTION, true, &pItem)) + bSelect = static_cast(pItem)->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( CRSR_SKIP_CELLS, bSelect, 1, false, true ); + break; + case FN_CHAR_RIGHT: + rSh.Right( CRSR_SKIP_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(); + 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(); + 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(); + 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(); + 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(); + 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 ) ); + 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 ); + } + 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 000000000..aadc698ac --- /dev/null +++ b/sw/source/uibase/shells/txtnum.cxx @@ -0,0 +1,310 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(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(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_NUMBER_BULLETS: + case SID_OUTLINE_BULLET: + { + SfxItemSet aSet( GetPool(), + svl::Items{} ); + SwDocShell* pDocSh = GetView().GetDocShell(); + const bool bHtml = dynamic_cast( 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, + " - 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( 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 pDlg(pFact->CreateSvxNumBulletTabDialog(pParent, &aSet, GetShell())); + const SfxStringItem* pPageItem = rReq.GetArg(FN_PARAM_1); + if ( pPageItem ) + pDlg->SetCurPageId( OUStringToOString( pPageItem->GetValue(), RTL_TEXTENCODING_UTF8 ) ); + + auto pRequest = std::make_shared(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + + pDlg->StartExecuteAsync([aSet, pDlg, pNumRuleAtCurrentSelection, pRequest, this](sal_Int32 nResult){ + if (RET_OK == nResult) + { + const SfxPoolItem* pItem; + if (SfxItemState::SET == pDlg->GetOutputItemSet()->GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem)) + { + pRequest->AppendItem(*pItem); + pRequest->Done(); + SvxNumRule* pSetRule = static_cast(pItem)->GetNumRule(); + pSetRule->UnLinkGraphics(); + SwNumRule aSetRule(pNumRuleAtCurrentSelection != nullptr + ? pNumRuleAtCurrentSelection->GetName() + : GetShell().GetUniqueNumRuleName(), + numfunc::GetDefaultPositionAndSpaceMode()); + aSetRule.SetSvxRule(*pSetRule, 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 + && SfxItemState::SET == aSet.GetItemState(SID_ATTR_NUMBERING_RULE, false, &pItem)) + { + pRequest->AppendItem(*pItem); + pRequest->Done(); + SvxNumRule* pSetRule = static_cast(pItem)->GetNumRule(); + SwNumRule aSetRule( + GetShell().GetUniqueNumRuleName(), + numfunc::GetDefaultPositionAndSpaceMode()); + aSetRule.SetSvxRule(*pSetRule, 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(nSlot); + if ( pItem != nullptr ) + { + const sal_uInt16 nChoosenItemIdx = 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, nChoosenItemIdx - 1, nActNumLvl ); + + aNewNumRule.SetSvxRule( aNewSvxNumRule, GetShell().GetDoc() ); + aNewNumRule.SetAutoRule( true ); + const bool bCreateNewList = ( pNumRuleAtCurrentSelection == nullptr ); + GetShell().SetCurNumRule( aNewNumRule, bCreateNewList ); + } + } + } + break; + + default: + OSL_ENSURE(false, "wrong Dispatcher"); + return; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/sidebar/PageColumnControl.cxx b/sw/source/uibase/sidebar/PageColumnControl.cxx new file mode 100644 index 000000000..1675867ac --- /dev/null +++ b/sw/source/uibase/sidebar/PageColumnControl.cxx @@ -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 . + */ + +#include +#include "PageColumnControl.hxx" +#include + +#include + +#include +#include +#include +#include +#include + +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; + const SfxPoolItem *pItem; + if ( SfxViewFrame::Current() ) + { + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE, pItem ); + bLandscape = static_cast(pItem)->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 ) +{ + std::unique_ptr mpPageColumnTypeItem( new SfxInt16Item(SID_ATTR_PAGE_COLUMN) ); + mpPageColumnTypeItem->SetValue( nColumnType ); + if ( SfxViewFrame::Current() ) + SfxViewFrame::Current()->GetBindings().GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLUMN, + SfxCallMode::RECORD, { mpPageColumnTypeItem.get() }); +} + +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::Current() ) + SfxViewFrame::Current()->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 000000000..140c94872 --- /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 +#include + +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 m_xOneColumn; + std::unique_ptr m_xTwoColumns; + std::unique_ptr m_xThreeColumns; + std::unique_ptr m_xLeft; + std::unique_ptr m_xRight; + std::unique_ptr m_xMoreButton; + + rtl::Reference 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 000000000..b0b9e07fc --- /dev/null +++ b/sw/source/uibase/sidebar/PageColumnPopup.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include "PageColumnControl.hxx" +#include +#include + +PageColumnPopup::PageColumnPopup(const css::uno::Reference& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageColumnPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageColumnPopup::~PageColumnPopup() +{ +} + +std::unique_ptr PageColumnPopup::weldPopupWindow() +{ + return std::make_unique(this, m_pToolbar); +} + +VclPtr PageColumnPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr::Create(getFrameInterface(), pParent, + std::make_unique(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageColumnPopup::getImplementationName() +{ + return "lo.writer.PageColumnToolBoxControl"; +} + +css::uno::Sequence 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 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 000000000..f7efb76a0 --- /dev/null +++ b/sw/source/uibase/sidebar/PageFooterPanel.cxx @@ -0,0 +1,295 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include "PageFooterPanel.hxx" +#include +#include +#include + +#include + +namespace sw::sidebar{ + +VclPtr PageFooterPanel::Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFooterPanel::Create", nullptr, 0); + if( !rxFrame.is() ) + throw ::com::sun::star::lang::IllegalArgumentException("no XFrame given to PageFooterPanel::Create", nullptr, 0); + + return VclPtr::Create(pParent, rxFrame, 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) : + PanelLayout(pParent, "PageFooterPanel", "modules/swriter/ui/pagefooterpanel.ui", rxFrame), + 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()), + aCustomEntry(), + 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() +{ + disposeOnce(); +} + +void PageFooterPanel::dispose() +{ + mxFooterToggle.reset(); + maMetricController.dispose(); + mxFooterSpacingLB.reset(); + mxFooterLayoutLB.reset(); + mxFooterMarginPresetLB.reset(); + mxCustomEntry.reset(); + + PanelLayout::dispose(); +} + +FieldUnit PageFooterPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState) +{ + FieldUnit eUnit; + + if (pState && eState >= SfxItemState::DEFAULT) + eUnit = static_cast(static_cast(pState)->GetValue()); + else + eUnit = GetModuleFieldUnit(); + + return eUnit; +} + +void PageFooterPanel::Initialize() +{ + SameContentListBox::Fill(*mxFooterLayoutLB); + + SetMarginsAndSpacingFieldUnit(); + + 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(aCustomEntry); + if (nCustomEntry != -1) + mxFooterMarginPresetLB->remove(nCustomEntry); + return; + } + } + } + mxFooterMarginPresetLB->append_text(aCustomEntry); + mxFooterMarginPresetLB->set_active_text(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(aCustomEntry); + if (nCustomEntry != -1) + mxFooterSpacingLB->remove(nCustomEntry); + return; + } + } + mxFooterSpacingLB->append_text(aCustomEntry); + mxFooterSpacingLB->set_active_text(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 (IsDisposed()) + return; + + switch(nSid) + { + case SID_ATTR_PAGE_FOOTER: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpFooterItem.reset( static_cast(pState->Clone()) ); + mxFooterToggle->set_active(mpFooterItem->GetValue()); + UpdateFooterCheck(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_LRMARGIN: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpFooterLRMarginItem.reset( static_cast(pState->Clone()) ); + UpdateMarginControl(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_SPACING: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpFooterSpacingItem.reset(static_cast(pState->Clone()) ); + UpdateSpacingControl(); + } + } + break; + case SID_ATTR_PAGE_FOOTER_LAYOUT: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpFooterLayoutItem.reset(static_cast(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::ToggleButton&, 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 000000000..849a3165d --- /dev/null +++ b/sw/source/uibase/sidebar/PageFooterPanel.hxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +namespace sw::sidebar { + +class PageFooterPanel: + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static VclPtr Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings); + virtual ~PageFooterPanel() override; + virtual void dispose() 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 aCustomEntry; + + void Initialize(); + void SetMarginsAndSpacingFieldUnit(); + void UpdateFooterCheck(); + void UpdateMarginControl(); + void UpdateSpacingControl(); + void UpdateLayoutControl(); + + ::std::unique_ptr mpFooterItem; + ::std::unique_ptr mpFooterLRMarginItem; + ::std::unique_ptr mpFooterSpacingItem; + ::std::unique_ptr mpFooterLayoutItem; + + std::unique_ptr mxFooterToggle; + std::unique_ptr mxFooterSpacingLB; + std::unique_ptr mxFooterMarginPresetLB; + std::unique_ptr mxFooterLayoutLB; + std::unique_ptr mxCustomEntry; + + static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState); + + DECL_LINK( FooterToggleHdl, weld::ToggleButton&, 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 000000000..7a13c6553 --- /dev/null +++ b/sw/source/uibase/sidebar/PageFormatPanel.cxx @@ -0,0 +1,432 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "PageFormatPanel.hxx" +#include "PageMarginUtils.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sw::sidebar{ + +VclPtr PageFormatPanel::Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageFormatPanel::Create", nullptr, 0); + if( !rxFrame.is() ) + throw ::com::sun::star::lang::IllegalArgumentException("no XFrame given to PageFormatPanel::Create", nullptr, 0); + + return VclPtr::Create(pParent, rxFrame, 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 (size_t i = 0; i < SAL_N_ELEMENTS(RID_PAGEFORMATPANEL_MARGINS_INCH); ++i) + { + OUString sStr = rLocaleData.getNum(RID_PAGEFORMATPANEL_MARGINS_INCH[i].second, 2, true, false) + sSuffix; + mxMarginSelectBox->append_text(SwResId(RID_PAGEFORMATPANEL_MARGINS_INCH[i].first).replaceFirst("%1", sStr)); + } + } + else + { + OUString sSuffix = weld::MetricSpinButton::MetricToString(FieldUnit::CM); + for (size_t i = 0; i < SAL_N_ELEMENTS(RID_PAGEFORMATPANEL_MARGINS_CM); ++i) + { + OUString sStr = rLocaleData.getNum(RID_PAGEFORMATPANEL_MARGINS_CM[i].second, 2, true, false) + " " + sSuffix; + mxMarginSelectBox->append_text(SwResId(RID_PAGEFORMATPANEL_MARGINS_CM[i].first).replaceFirst("%1", sStr)); + } + } + mxMarginSelectBox->set_active(nSelected); +} + +PageFormatPanel::PageFormatPanel( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) : + PanelLayout(pParent, "PageFormatPanel", "modules/swriter/ui/pageformatpanel.ui", rxFrame), + 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(), + aCustomEntry() +{ + Initialize(); +} + +PageFormatPanel::~PageFormatPanel() +{ + disposeOnce(); +} + +void PageFormatPanel::dispose() +{ + 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(); + + PanelLayout::dispose(); +} + +void PageFormatPanel::Initialize() +{ + mxPaperSizeBox->FillPaperSizeEntries( PaperSizeApp::Std ); + meUnit = maPaperSizeController.GetCoreMetric(); + mxPaperWidth->SetFieldUnit(meFUnit); + mxPaperHeight->SetFieldUnit(meFUnit); + SetMarginFieldUnit(); + aCustomEntry = mxCustomEntry->get_label(); + + const SvtOptionsDrawinglayer aDrawinglayerOpt; + mxPaperWidth->set_max(mxPaperWidth->normalize(aDrawinglayerOpt.GetMaximumPaperWidth()), FieldUnit::CM); + mxPaperHeight->set_max(mxPaperHeight->normalize(aDrawinglayerOpt.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(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(pState->Clone()) ); + UpdateMarginBox(); + } + } + break; + case SID_ATTR_PAGE_ULSPACE: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxLongULSpaceItem *>( pState ) ) + { + mpPageULMarginItem.reset( static_cast(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(static_cast(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(static_cast(pItem)->GetValue()); + } + else + { + SAL_WARN("sw.ui", "GetModuleFieldUnit(): no module found"); + } + } + } + + return eUnit; +} + +void PageFormatPanel::ExecuteMarginLRChange( const long nPageLeftMargin, const long nPageRightMargin ) +{ + mpPageLRMarginItem->SetLeft( nPageLeftMargin ); + mpPageLRMarginItem->SetRight( nPageRightMargin ); + mpBindings->GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE, SfxCallMode::RECORD, { mpPageLRMarginItem.get() }); +} + +void PageFormatPanel::ExecuteMarginULChange(const long nPageTopMargin, const 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(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(aCustomEntry); + mxMarginSelectBox->set_active_text(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 000000000..4ea09bb50 --- /dev/null +++ b/sw/source/uibase/sidebar/PageFormatPanel.hxx @@ -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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFORMATPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEFORMATPANEL_HXX + +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace sw::sidebar { + +class PageFormatPanel: + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static VclPtr Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings); + virtual ~PageFormatPanel() override; + virtual void dispose() override; + + static FieldUnit GetCurrentUnit( SfxItemState eState, const SfxPoolItem* pState ); + +private: + + SfxBindings* mpBindings; + + std::unique_ptr mxPaperSizeBox; + std::unique_ptr mxPaperWidth; + std::unique_ptr mxPaperHeight; + std::unique_ptr mxPaperOrientation; + std::unique_ptr mxMarginSelectBox; + std::unique_ptr mxCustomEntry; + + ::sfx2::sidebar::ControllerItem maPaperSizeController; + ::sfx2::sidebar::ControllerItem maPaperOrientationController; + ::sfx2::sidebar::ControllerItem maMetricController; + ::sfx2::sidebar::ControllerItem maSwPageLRControl; + ::sfx2::sidebar::ControllerItem maSwPageULControl; + + std::unique_ptr mpPageItem; + std::unique_ptr mpPageLRMarginItem; + std::unique_ptr mpPageULMarginItem; + + FieldUnit meFUnit; + MapUnit meUnit; + + long mnPageLeftMargin; + long mnPageRightMargin; + long mnPageTopMargin; + long mnPageBottomMargin; + OUString aCustomEntry; + + void Initialize(); + void SetMarginFieldUnit(); + void UpdateMarginBox(); + void ExecuteMarginLRChange( const long nPageLeftMargin, const long nPageRightMargin ); + void ExecuteMarginULChange( const long nPageTopMargin, const 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 + +#endif + +/* 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 000000000..a81d07a29 --- /dev/null +++ b/sw/source/uibase/sidebar/PageHeaderPanel.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include "PageHeaderPanel.hxx" +#include +#include +#include + +#include + +namespace sw::sidebar{ + +VclPtr PageHeaderPanel::Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageHeaderPanel::Create", nullptr, 0); + if( !rxFrame.is() ) + throw ::com::sun::star::lang::IllegalArgumentException("no XFrame given to PageHeaderPanel::Create", nullptr, 0); + if( pBindings == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageHeaderPanel::Create", nullptr, 0); + + return VclPtr::Create(pParent, rxFrame, 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings + ) : + PanelLayout(pParent, "PageHeaderPanel", "modules/swriter/ui/pageheaderpanel.ui", rxFrame), + 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()), + aCustomEntry(), + 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() +{ + disposeOnce(); +} + +void PageHeaderPanel::dispose() +{ + mxHeaderToggle.reset(); + mxHeaderSpacingLB.reset(); + mxHeaderLayoutLB.reset(); + mxHeaderMarginPresetLB.reset(); + mxCustomEntry.reset(); + + PanelLayout::dispose(); +} + +FieldUnit PageHeaderPanel::GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState) +{ + FieldUnit eUnit; + + if (pState && eState >= SfxItemState::DEFAULT) + eUnit = static_cast(static_cast(pState)->GetValue()); + else + eUnit = GetModuleFieldUnit(); + + return eUnit; +} + +void PageHeaderPanel::Initialize() +{ + SameContentListBox::Fill(*mxHeaderLayoutLB); + + SetMarginsAndSpacingFieldUnit(); + + 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(aCustomEntry); + if (nCustomEntry != -1) + mxHeaderMarginPresetLB->remove(nCustomEntry); + return; + } + } + } + mxHeaderMarginPresetLB->append_text(aCustomEntry); + mxHeaderMarginPresetLB->set_active_text(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(aCustomEntry); + if (nCustomEntry != -1) + mxHeaderSpacingLB->remove(nCustomEntry); + return; + } + } + mxHeaderSpacingLB->append_text(aCustomEntry); + mxHeaderSpacingLB->set_active_text(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 (IsDisposed()) + return; + + switch(nSid) + { + case SID_ATTR_PAGE_HEADER: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpHeaderItem.reset( static_cast(pState->Clone()) ); + mxHeaderToggle->set_active(mpHeaderItem->GetValue()); + UpdateHeaderCheck(); + } + } + break; + case SID_ATTR_PAGE_HEADER_LRMARGIN: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpHeaderLRMarginItem.reset( static_cast(pState->Clone()) ); + UpdateMarginControl(); + } + } + break; + case SID_ATTR_PAGE_HEADER_SPACING: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpHeaderSpacingItem.reset(static_cast(pState->Clone()) ); + UpdateSpacingControl(); + } + } + break; + case SID_ATTR_PAGE_HEADER_LAYOUT: + { + if(eState >= SfxItemState::DEFAULT && + dynamic_cast( pState) ) + { + mpHeaderLayoutItem.reset(static_cast(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::ToggleButton&, 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 000000000..c7701f9e7 --- /dev/null +++ b/sw/source/uibase/sidebar/PageHeaderPanel.hxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_PAGEHEADERPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEHEADERPANEL_HXX + +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +namespace sw::sidebar { + +class PageHeaderPanel: + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static VclPtr Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings); + virtual ~PageHeaderPanel() override; + virtual void dispose() 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 aCustomEntry; + + void Initialize(); + void SetMarginsAndSpacingFieldUnit(); + void UpdateHeaderCheck(); + void UpdateMarginControl(); + void UpdateSpacingControl(); + void UpdateLayoutControl(); + + ::std::unique_ptr mpHeaderItem; + ::std::unique_ptr mpHeaderLRMarginItem; + ::std::unique_ptr mpHeaderSpacingItem; + ::std::unique_ptr mpHeaderLayoutItem; + + std::unique_ptr mxHeaderToggle; + std::unique_ptr mxHeaderSpacingLB; + std::unique_ptr mxHeaderMarginPresetLB; + std::unique_ptr mxHeaderLayoutLB; + std::unique_ptr mxCustomEntry; + + static FieldUnit GetCurrentUnit(SfxItemState eState, const SfxPoolItem* pState); + + DECL_LINK( HeaderToggleHdl, weld::ToggleButton&, void ); + DECL_LINK( HeaderLRMarginHdl, weld::ComboBox&, void); + DECL_LINK( HeaderSpacingHdl, weld::ComboBox&, void); + DECL_LINK( HeaderLayoutHdl, weld::ComboBox&, void); +}; + +} //end of namespace sw::sidebar + +#endif + +/* 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 000000000..258b5996d --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginControl.cxx @@ -0,0 +1,586 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include "PageMarginControl.hxx" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define SWPAGE_LEFT_GVALUE "Sw_Page_Left" +#define SWPAGE_RIGHT_GVALUE "Sw_Page_Right" +#define SWPAGE_TOP_GVALUE "Sw_Page_Top" +#define SWPAGE_DOWN_GVALUE "Sw_Page_Down" +#define SWPAGE_MIRROR_GVALUE "Sw_Page_Mirrored" + +namespace +{ + FieldUnit lcl_GetFieldUnit() + { + FieldUnit eUnit = FieldUnit::INCH; + const SfxPoolItem* pItem = nullptr; + SfxItemState eState = SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_METRIC, pItem ); + if ( pItem && eState >= SfxItemState::DEFAULT ) + { + eUnit = static_cast(static_cast( pItem )->GetValue()); + } + else + { + return SfxModule::GetCurrentFieldUnit(); + } + + return eUnit; + } + + 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_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 SfxPoolItem* pItem; + const SvxSizeItem* pSize = nullptr; + const SvxLongLRSpaceItem* pLRItem = nullptr; + const SvxLongULSpaceItem* pULItem = nullptr; + if ( SfxViewFrame::Current() ) + { + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE, pItem ); + bLandscape = static_cast( pItem )->IsLandscape(); + m_bMirrored = static_cast( pItem )->GetPageUsage() == SvxPageUsage::Mirror; + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE_SIZE, pItem ); + pSize = static_cast( pItem ); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE_LRSPACE, pItem ); + pLRItem = static_cast( pItem ); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE_ULSPACE, pItem ); + pULItem = static_cast( pItem ); + } + + 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_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_bUserCustomValuesAvailable = GetUserCustomValues(); + + FillHelpText( m_bUserCustomValuesAvailable ); + + Link 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 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() ); + + 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_xNarrow->grab_focus(); +} + +PageMarginControl::~PageMarginControl() +{ + StoreUserCustomValues(); +} + +void PageMarginControl::SetMetricFieldMaxValues( const Size& rPageSize ) +{ + const long nML = m_xLeftMarginEdit->denormalize( m_xLeftMarginEdit->get_value( FieldUnit::TWIP ) ); + const long nMR = m_xRightMarginEdit->denormalize( m_xRightMarginEdit->get_value( FieldUnit::TWIP ) ); + const long nMT = m_xTopMarginEdit->denormalize( m_xTopMarginEdit->get_value( FieldUnit::TWIP ) ); + const long nMB = m_xBottomMarginEdit->denormalize( m_xBottomMarginEdit->get_value( FieldUnit::TWIP ) ); + + const long nPH = OutputDevice::LogicToLogic( rPageSize.Height(), m_eUnit, MapUnit::MapTwip ); + const long nPW = OutputDevice::LogicToLogic( rPageSize.Width(), m_eUnit, MapUnit::MapTwip ); + + // Left + 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(); + aHelpText += aTop; + SetMetricValue( *m_xWidthHeightField, m_nUserCustomPageTopMargin, m_eUnit ); + aHelpText += m_xWidthHeightField->get_text(); + aHelpText += 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 ) + { + const css::uno::Reference< css::document::XUndoManager > xUndoManager( getUndoManager( SfxViewFrame::Current()->GetFrame().GetFrameInterface() ) ); + 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 long nPageLeftMargin, + const long nPageRightMargin ) +{ + if ( SfxViewFrame::Current() ) + { + std::unique_ptr pPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) ); + pPageLRMarginItem->SetLeft( nPageLeftMargin ); + pPageLRMarginItem->SetRight( nPageRightMargin ); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_LRSPACE, + SfxCallMode::RECORD, { pPageLRMarginItem.get() } ); + pPageLRMarginItem.reset(); + } +} + +void PageMarginControl::ExecuteMarginULChange( + const long nPageTopMargin, + const long nPageBottomMargin ) +{ + if ( SfxViewFrame::Current() ) + { + std::unique_ptr pPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) ); + pPageULMarginItem->SetUpper( nPageTopMargin ); + pPageULMarginItem->SetLower( nPageBottomMargin ); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE_ULSPACE, + SfxCallMode::RECORD, { pPageULMarginItem.get() } ); + pPageULMarginItem.reset(); + } +} + +void PageMarginControl::ExecutePageLayoutChange( const bool bMirrored ) +{ + if ( SfxViewFrame::Current() ) + { + std::unique_ptr pPageItem( new SvxPageItem( SID_ATTR_PAGE ) ); + pPageItem->SetPageUsage( bMirrored ? SvxPageUsage::Mirror : SvxPageUsage::All ); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->ExecuteList( SID_ATTR_PAGE, + SfxCallMode::RECORD, { pPageItem.get() } ); + pPageItem.reset(); + } +} + +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; +} + +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 ); + SvtViewOptions aWinOpt( EViewType::Window, SWPAGE_LEFT_GVALUE ); + + aSeq[0].Name = "mnPageLeftMargin"; + aSeq[0].Value <<= OUString::number( m_nPageLeftMargin ); + aWinOpt.SetUserData( aSeq ); + + SvtViewOptions aWinOpt2( EViewType::Window, SWPAGE_RIGHT_GVALUE ); + aSeq[0].Name = "mnPageRightMargin"; + aSeq[0].Value <<= OUString::number( m_nPageRightMargin ); + aWinOpt2.SetUserData( aSeq ); + + SvtViewOptions aWinOpt3( EViewType::Window, SWPAGE_TOP_GVALUE ); + aSeq[0].Name = "mnPageTopMargin"; + aSeq[0].Value <<= OUString::number( m_nPageTopMargin ); + aWinOpt3.SetUserData( aSeq ); + + SvtViewOptions aWinOpt4( EViewType::Window, SWPAGE_DOWN_GVALUE ); + aSeq[0].Name = "mnPageBottomMargin"; + aSeq[0].Value <<= OUString::number( m_nPageBottomMargin ); + aWinOpt4.SetUserData( aSeq ); + + SvtViewOptions aWinOpt5( EViewType::Window, SWPAGE_MIRROR_GVALUE ); + aSeq[0].Name = "mbMirrored"; + aSeq[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 000000000..1c945e815 --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginControl.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#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 +static const long MINBODY = 56; // 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 m_xNarrow; + std::unique_ptr m_xNormal; + std::unique_ptr m_xWide; + std::unique_ptr m_xMirrored; + std::unique_ptr m_xLast; + + std::unique_ptr m_xLeft; + std::unique_ptr m_xRight; + std::unique_ptr m_xInner; + std::unique_ptr m_xOuter; + + std::unique_ptr m_xLeftMarginEdit; + std::unique_ptr m_xRightMarginEdit; + std::unique_ptr m_xTopMarginEdit; + std::unique_ptr m_xBottomMarginEdit; + + // hidden metric field + std::unique_ptr m_xWidthHeightField; + + rtl::Reference m_xControl; + + long m_nPageLeftMargin; + long m_nPageRightMargin; + long m_nPageTopMargin; + long m_nPageBottomMargin; + bool m_bMirrored; + + const MapUnit m_eUnit; + + Size m_aPageSize; + + bool m_bUserCustomValuesAvailable; + long m_nUserCustomPageLeftMargin; + long m_nUserCustomPageRightMargin; + long m_nUserCustomPageTopMargin; + 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 ); + + static void ExecuteMarginLRChange( + const long nPageLeftMargin, + const long nPageRightMargin ); + static void ExecuteMarginULChange( + const long nPageTopMargin, + const 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 000000000..8223386c2 --- /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 +#include "PageMarginControl.hxx" +#include + +PageMarginPopup::PageMarginPopup(const css::uno::Reference& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageMarginPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageMarginPopup::~PageMarginPopup() +{ +} + +std::unique_ptr PageMarginPopup::weldPopupWindow() +{ + return std::make_unique(this, m_pToolbar); +} + +VclPtr PageMarginPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr::Create(getFrameInterface(), pParent, + std::make_unique(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageMarginPopup::getImplementationName() +{ + return "lo.writer.PageMarginToolBoxControl"; +} + +css::uno::Sequence 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 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 000000000..1361361a1 --- /dev/null +++ b/sw/source/uibase/sidebar/PageMarginUtils.hxx @@ -0,0 +1,192 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 long nPageLeftMargin, const long nPageRightMargin, + const long nPageTopMargin, const 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( long& nPageLeftMargin, long& nPageRightMargin, + long& nPageTopMargin, 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 000000000..d44dd3a5b --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationControl.cxx @@ -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 "PageOrientationControl.hxx" +#include "PageMarginControl.hxx" +#include +#include +#include +#include + +#include +#include +#include +#include + +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 long nPageLeftMargin, + const long nPageRightMargin ) +{ + mpPageLRMarginItem->SetLeft( nPageLeftMargin ); + mpPageLRMarginItem->SetRight( nPageRightMargin ); + SfxViewShell::Current()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_LRSPACE, + SfxCallMode::RECORD, { mpPageLRMarginItem.get() }); +} + +void PageOrientationControl::ExecuteMarginULChange( + const long nPageTopMargin, + const long nPageBottomMargin ) +{ + mpPageULMarginItem->SetUpper( nPageTopMargin ); + mpPageULMarginItem->SetLower( nPageBottomMargin ); + SfxViewShell::Current()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_ULSPACE, + SfxCallMode::RECORD, { mpPageULMarginItem.get() }); +} + +void PageOrientationControl::ExecuteOrientationChange( const bool bLandscape ) +{ + css::uno::Reference< css::document::XUndoManager > mxUndoManager( + getUndoManager( SfxViewFrame::Current()->GetFrame().GetFrameInterface() ) ); + + if ( mxUndoManager.is() ) + mxUndoManager->enterUndoContext( "" ); + + const SfxPoolItem* pItem; + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, pItem); + mpPageSizeItem.reset( static_cast(pItem->Clone()) ); + + // Prevent accidental toggling of page orientation + if ((mpPageSizeItem->GetWidth() > mpPageSizeItem->GetHeight()) == bLandscape) + { + if ( mxUndoManager.is() ) + mxUndoManager->leaveUndoContext(); + return; + } + + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, pItem); + mpPageLRMarginItem.reset( static_cast(pItem->Clone()) ); + + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, pItem); + mpPageULMarginItem.reset( static_cast(pItem->Clone()) ); + + { + // set new page orientation + mpPageItem->SetLandscape( bLandscape ); + + // swap the width and height of the page size + const long nRotatedWidth = mpPageSizeItem->GetSize().Height(); + const long nRotatedHeight = mpPageSizeItem->GetSize().Width(); + mpPageSizeItem->SetSize(Size(nRotatedWidth, nRotatedHeight)); + + // apply changed attributes + if (SfxViewShell::Current()) + { + SfxViewShell::Current()->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 long nML = mpPageLRMarginItem->GetLeft(); + const long nMR = mpPageLRMarginItem->GetRight(); + const long nTmpPW = nML + nMR + MINBODY; + + const 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 long nMT = mpPageULMarginItem->GetUpper(); + const long nMB = mpPageULMarginItem->GetLower(); + const long nTmpPH = nMT + nMB + MINBODY; + + const 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 000000000..7cb825406 --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationControl.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_SIDEBAR_PAGEORIENTATIONCONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGEORIENTATIONCONTROL_HXX + +#include +#include +#include +#include +#include + +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 m_xPortrait; + std::unique_ptr m_xLandscape; + rtl::Reference m_xControl; + + std::unique_ptr mpPageItem; + std::unique_ptr mpPageSizeItem; + std::unique_ptr mpPageLRMarginItem; + std::unique_ptr mpPageULMarginItem; + + void ExecuteMarginULChange(const long nPageTopMargin, const long nPageBottomMargin); + void ExecuteMarginLRChange(const long nPageLeftMargin, const long nPageRightMargin); + void ExecuteOrientationChange(const bool bLandscape); + + DECL_LINK(ImplOrientationHdl, weld::Button&, void); +}; + +} // end of namespace sw::sidebar + +#endif + +/* 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 000000000..9b34f3c1d --- /dev/null +++ b/sw/source/uibase/sidebar/PageOrientationPopup.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include "PageOrientationControl.hxx" +#include +#include + +PageOrientationPopup::PageOrientationPopup(const css::uno::Reference& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageOrientationPopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageOrientationPopup::~PageOrientationPopup() +{ +} + +std::unique_ptr PageOrientationPopup::weldPopupWindow() +{ + return std::make_unique(this, m_pToolbar); +} + +VclPtr PageOrientationPopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr::Create(getFrameInterface(), pParent, + std::make_unique(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageOrientationPopup::getImplementationName() +{ + return "lo.writer.PageOrientationToolBoxControl"; +} + +css::uno::Sequence 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 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 000000000..5abdb4788 --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizeControl.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include "PageSizeControl.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace +{ + FieldUnit lcl_GetFieldUnit() + { + FieldUnit eUnit = FieldUnit::INCH; + const SfxPoolItem* pItem = nullptr; + SfxItemState eState = SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_METRIC, pItem ); + if ( pItem && eState >= SfxItemState::DEFAULT ) + { + eUnit = static_cast(static_cast(pItem)->GetValue()); + } + else + { + return SfxModule::GetCurrentFieldUnit(); + } + + return eUnit; + } + + 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, "valueset", *mxSizeValueSet)) + , mxControl(pControl) + , maPaperList() +{ + 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 SfxPoolItem* pItem; + const SvxSizeItem* pSize = nullptr; + if ( SfxViewFrame::Current() ) + { + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE, pItem ); + bLandscape = static_cast(pItem)->IsLandscape(); + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE_SIZE, pItem ); + pSize = static_cast(pItem); + } + + 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->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; + const SfxPoolItem *pItem; + MapUnit eUnit = lcl_GetUnit(); + if ( SfxViewFrame::Current() ) + { + SfxViewFrame::Current()->GetBindings().GetDispatcher()->QueryState( SID_ATTR_PAGE, pItem ); + bLandscape = static_cast(pItem)->IsLandscape(); + + std::unique_ptr pPageSizeItem( new SvxSizeItem(SID_ATTR_PAGE_SIZE) ); + Size aPageSize = SvxPaperInfo::GetPaperSize( ePaper, eUnit ); + if ( bLandscape ) + { + Swap( aPageSize ); + } + pPageSizeItem->SetSize( aPageSize ); + + SfxViewFrame::Current()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE, + SfxCallMode::RECORD, { pPageSizeItem.get() }); + } +} + + +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::Current() ) + SfxViewFrame::Current()->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 000000000..be43d0900 --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizeControl.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 . + */ +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESIZECONTROL_HXX + +#include + +#include +#include + +#include + +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 mxMoreButton; + // hidden metric field + std::unique_ptr mxWidthHeightField; + std::unique_ptr mxSizeValueSet; + std::unique_ptr mxSizeValueSetWin; + rtl::Reference 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 000000000..0c69f73ba --- /dev/null +++ b/sw/source/uibase/sidebar/PageSizePopup.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include "PageSizeControl.hxx" +#include +#include + +PageSizePopup::PageSizePopup(const css::uno::Reference& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void PageSizePopup::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +PageSizePopup::~PageSizePopup() +{ +} + +std::unique_ptr PageSizePopup::weldPopupWindow() +{ + return std::make_unique(this, m_pToolbar); +} + +VclPtr PageSizePopup::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr::Create(getFrameInterface(), pParent, + std::make_unique(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString PageSizePopup::getImplementationName() +{ + return "lo.writer.PageSizeToolBoxControl"; +} + +css::uno::Sequence 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 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 000000000..1815466c1 --- /dev/null +++ b/sw/source/uibase/sidebar/PageStylesPanel.cxx @@ -0,0 +1,604 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "PageStylesPanel.hxx" +#include +#include +#include +#include + +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]; +} + +VclPtr PageStylesPanel::Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings) +{ + if( pParent == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no parent window given to PageStylesPanel::Create", nullptr, 0); + if( !rxFrame.is() ) + throw ::com::sun::star::lang::IllegalArgumentException("no XFrame given to PageStylesPanel::Create", nullptr, 0); + if( pBindings == nullptr ) + throw ::com::sun::star::lang::IllegalArgumentException("no SfxBindings given to PageStylesPanel::Create", nullptr, 0); + + return VclPtr::Create(pParent, rxFrame, pBindings); +} + +PageStylesPanel::PageStylesPanel( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings + ) : + PanelLayout(pParent, "PageStylesPanel", "modules/swriter/ui/pagestylespanel.ui", rxFrame), + 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"), GetFrameWeld())), + mxBgHatchingLB(m_xBuilder->weld_combo_box("lbhatching")), + mxBgGradientLB(new ColorListBox(m_xBuilder->weld_menu_button("lbgradient"), 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")), + aCustomEntry() +{ + Initialize(); +} + +PageStylesPanel::~PageStylesPanel() +{ + disposeOnce(); +} + +void PageStylesPanel::dispose() +{ + 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(); + PanelLayout::dispose(); +} + +void PageStylesPanel::Initialize() +{ + SvxFillTypeBox::Fill(*mxBgFillType); + + 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::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(mxBgFillType->get_active()); + SfxObjectShell* pSh = SfxObjectShell::Current(); + 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 XGradient xGradient = GetGradientSetOrDefault(); + const Color aStartColor = xGradient.GetStartColor(); + mxBgColorLB->SelectEntry(aStartColor); + const Color aEndColor = xGradient.GetEndColor(); + 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; + } +} + +Color const & PageStylesPanel::GetColorSetOrDefault() +{ + if ( !mpBgColorItem ) + mpBgColorItem.reset( new XFillColorItem( OUString(), Color(0x72, 0x9f, 0xcf) ) ); + + return mpBgColorItem->GetColorValue(); +} + +XGradient const & PageStylesPanel::GetGradientSetOrDefault() +{ + if( !mpBgGradientItem ) + { + SfxObjectShell* pSh = SfxObjectShell::Current(); + const SvxGradientListItem * pGradListItem = pSh->GetItem(SID_GRADIENT_LIST); + const XGradient aGradient = pGradListItem->GetGradientList()->GetGradient(0)->GetGradient(); + const OUString aGradientName = pGradListItem->GetGradientList()->GetGradient(0)->GetName(); + + mpBgGradientItem.reset( new XFillGradientItem( aGradientName, aGradient ) ); + } + + return mpBgGradientItem->GetGradientValue(); +} + +OUString const & PageStylesPanel::GetHatchingSetOrDefault() +{ + if( !mpBgHatchItem ) + { + SfxObjectShell* pSh = SfxObjectShell::Current(); + const SvxHatchListItem * pHatchListItem = pSh->GetItem(SID_HATCH_LIST); + const XHatch aHatch = pHatchListItem->GetHatchList()->GetHatch(0)->GetHatch(); + const OUString aHatchName = pHatchListItem->GetHatchList()->GetHatch(0)->GetName(); + + mpBgHatchItem.reset( new XFillHatchItem( aHatchName, aHatch ) ); + } + + return mpBgHatchItem->GetName(); +} + +OUString const & PageStylesPanel::GetBitmapSetOrDefault() +{ + if( !mpBgBitmapItem || mpBgBitmapItem->isPattern() ) + { + SfxObjectShell* pSh = SfxObjectShell::Current(); + const SvxBitmapListItem * pBmpListItem = pSh->GetItem(SID_BITMAP_LIST); + const GraphicObject aGraphObj = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetGraphicObject(); + const OUString aBmpName = pBmpListItem->GetBitmapList()->GetBitmap(0)->GetName(); + + mpBgBitmapItem.reset( new XFillBitmapItem( aBmpName, aGraphObj ) ); + } + + return mpBgBitmapItem->GetName(); +} + +OUString const & PageStylesPanel::GetPatternSetOrDefault() +{ + if( !mpBgBitmapItem || !mpBgBitmapItem->isPattern() ) + { + SfxObjectShell* pSh = SfxObjectShell::Current(); + const SvxPatternListItem * pPatternListItem = pSh->GetItem(SID_PATTERN_LIST); + const GraphicObject aGraphObj = pPatternListItem->GetPatternList()->GetBitmap(0)->GetGraphicObject(); + const OUString 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(IsDisposed()) + return; + + switch(nSid) + { + case SID_ATTR_PAGE_COLUMN: + { + if ( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SfxInt16Item *>( pState ) ) + { + mpPageColumnItem.reset( static_cast(pState->Clone()) ); + if(mpPageColumnItem->GetValue() <= 5) + { + mxColumnCount->set_active(mpPageColumnItem->GetValue() - 1); + int nIndex = mxColumnCount->find_text(aCustomEntry); + if (nIndex != -1) + mxColumnCount->remove(nIndex); + } + else + { + if (mxColumnCount->find_text(aCustomEntry) == -1) + mxColumnCount->append_text(aCustomEntry); + mxColumnCount->set_active_text(aCustomEntry); + } + } + } + break; + + case SID_ATTR_PAGE: + { + if( eState >= SfxItemState::DEFAULT && + dynamic_cast< const SvxPageItem*>( pState ) ) + { + mpPageItem.reset( static_cast(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(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(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(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(PATTERN) ); + else + mxBgFillType->set_active( static_cast(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(NONE) ); + break; + case drawing::FillStyle_SOLID: + mxBgFillType->set_active( static_cast(SOLID) ); + break; + case drawing::FillStyle_GRADIENT: + mxBgFillType->set_active( static_cast(GRADIENT) ); + break; + case drawing::FillStyle_HATCH: + mxBgFillType->set_active( static_cast(HATCH) ); + break; + case drawing::FillStyle_BITMAP: + if (mpBgBitmapItem->isPattern()) + mxBgFillType->set_active( static_cast(PATTERN) ); + else + mxBgFillType->set_active( static_cast(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(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(mxBgFillType->get_active()); + SfxObjectShell* pSh = SfxObjectShell::Current(); + switch(eXFS) + { + case SOLID: + { + XFillColorItem aItem(OUString(), mxBgColorLB->GetSelectEntryColor()); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_COLOR, SfxCallMode::RECORD, { &aItem }); + } + break; + case GRADIENT: + { + XGradient aGradient; + aGradient.SetStartColor(mxBgColorLB->GetSelectEntryColor()); + aGradient.SetEndColor(mxBgGradientLB->GetSelectEntryColor()); + + XFillGradientItem aItem(aGradient); + GetBindings()->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_GRADIENT, SfxCallMode::RECORD, { &aItem }); + } + break; + case HATCH: + { + 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: + { + 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 000000000..7e3c09d2e --- /dev/null +++ b/sw/source/uibase/sidebar/PageStylesPanel.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_SIDEBAR_PAGESTYLESPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_PAGESTYLESPANEL_HXX + +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class List; +class ColorListBox; +namespace sw::sidebar { + +class PageStylesPanel: + public PanelLayout, + public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ +public: + static VclPtr Create( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + 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( + vcl::Window* pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rxFrame, + SfxBindings* pBindings); + virtual ~PageStylesPanel() override; + virtual void dispose() override; + +private: + + SfxBindings* mpBindings; + + ::std::unique_ptr mpPageColumnItem; + ::std::unique_ptr mpPageItem; + ::std::unique_ptr mpBgColorItem; + ::std::unique_ptr mpBgGradientItem; + ::std::unique_ptr mpBgHatchItem; + ::std::unique_ptr 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 mxBgColorLB; + std::unique_ptr mxBgHatchingLB; + std::unique_ptr mxBgGradientLB; + std::unique_ptr mxBgBitmapLB; + std::unique_ptr mxLayoutSelectLB; + std::unique_ptr mxColumnCount; + std::unique_ptr mxNumberSelectLB; + std::unique_ptr mxBgFillType; + std::unique_ptr mxCustomEntry; + OUString aCustomEntry; + + void Initialize(); + void Update(); + Color const & GetColorSetOrDefault(); + XGradient 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 000000000..4d82afe29 --- /dev/null +++ b/sw/source/uibase/sidebar/StylePresetsPanel.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include "StylePresetsPanel.hxx" + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + +namespace sw::sidebar { + +namespace { + +void renderPreview(sfx2::StyleManager* pStyleManager, OutputDevice& aOutputDevice, + OUString const & sName, sal_Int32 nHeight, tools::Rectangle const & aRect) +{ + SfxStyleSheetBase* pStyleSheet = pStyleManager->Search(sName, SfxStyleFamily::Para); + + if (pStyleSheet) + { + std::unique_ptr 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 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(); + + 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, "Title", nTitleHeight, aRenderRect); + y += nTitleHeight; + } + + { + tools::Rectangle aRenderRect(Point(nMargin, y), aSize); + renderPreview(pStyleManager, *pVirtualDev, "Heading 1", nHeadingHeight, aRenderRect); + y += nHeadingHeight; + } + { + tools::Rectangle aRenderRect(Point(nMargin, y), aSize); + renderPreview(pStyleManager, *pVirtualDev, "Text Body", nTextBodyHeight, aRenderRect); + } + + return pVirtualDev->GetBitmapEx(Point(), aSize); +} + +BitmapEx CreatePreview(OUString const & aUrl, OUString const & aName) +{ + SfxMedium aMedium(aUrl, StreamMode::STD_READWRITE); + SfxObjectShell* pObjectShell = SfxObjectShell::Current(); + SfxObjectShellLock xTemplDoc = SfxObjectShell::CreateObjectByFactoryName(pObjectShell->GetFactory().GetFactoryName(), SfxObjectCreateMode::ORGANIZER); + xTemplDoc->DoInitNew(); + if (xTemplDoc->LoadFrom(aMedium)) + { + return GenerateStylePreview(*xTemplDoc, aName); + } + return BitmapEx(); +} + +} + +VclPtr StylePresetsPanel::Create (vcl::Window* pParent, + const css::uno::Reference& rxFrame) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException("no parent Window given to StylePresetsPanel::Create", nullptr, 0); + if (!rxFrame.is()) + throw css::lang::IllegalArgumentException("no XFrame given to StylePresetsPanel::Create", nullptr, 1); + + return VclPtr::Create(pParent, rxFrame); +} + +StylePresetsPanel::StylePresetsPanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame) + : PanelLayout(pParent, "StylePresetsPanel", "modules/swriter/ui/sidebarstylepresets.ui", rxFrame) + , mxValueSet(new ValueSet(nullptr)) + , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxValueSet)) +{ + mxValueSet->SetColCount(2); + + 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(aURL)); + mxValueSet->SetItemData(nId, maTemplateEntries.back().get()); + } + mxValueSet->SetOptimalSize(); + } + } +} + +StylePresetsPanel::~StylePresetsPanel() +{ + disposeOnce(); +} + +void StylePresetsPanel::dispose() +{ + mxValueSetWin.reset(); + mxValueSet.reset(); + + PanelLayout::dispose(); +} + +IMPL_LINK_NOARG(StylePresetsPanel, DoubleClickHdl, ValueSet*, void) +{ + sal_Int32 nItemId = mxValueSet->GetSelectedItemId(); + TemplateEntry* pEntry = static_cast(mxValueSet->GetItemData(nItemId)); + + SwDocShell* pDocSh = static_cast(SfxObjectShell::Current()); + if (pDocSh) + { + 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 000000000..c217710be --- /dev/null +++ b/sw/source/uibase/sidebar/StylePresetsPanel.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/. + * + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_STYLEPRESETSPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_STYLEPRESETSPANEL_HXX + +#include +#include + +#include + +#include + +#include + +namespace sw::sidebar { + +class StylePresetsPanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ + friend class VclPtr; +public: + static VclPtr Create(vcl::Window* pParent, + const css::uno::Reference& rxFrame); + + 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(const OUString& rURL) + : maURL(rURL) + {} + + OUString maURL; + }; + + void RefreshList(); + + StylePresetsPanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame); + + virtual ~StylePresetsPanel() override; + virtual void dispose() override; + + std::unique_ptr mxValueSet; + std::unique_ptr mxValueSetWin; + + std::vector> maTemplateEntries; + + DECL_LINK(DoubleClickHdl, ValueSet*, void); +}; + +} // end of namespace sw::sidebar + +#endif // INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_STYLEPRESETSPANEL_HXX + +/* 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 000000000..37b6694e4 --- /dev/null +++ b/sw/source/uibase/sidebar/SwPanelFactory.cxx @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include "ThemePanel.hxx" +#include "StylePresetsPanel.hxx" +#include "PageStylesPanel.hxx" +#include "PageFormatPanel.hxx" +#include "PageHeaderPanel.hxx" +#include "PageFooterPanel.hxx" +#include "WrapPropertyPanel.hxx" +#include "TableEditPanel.hxx" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace css; +using namespace css::uno; + +namespace { + +typedef ::cppu::WeakComponentImplHelper < + css::ui::XUIElementFactory, css::lang::XServiceInfo + > PanelFactoryInterfaceBase; + +class SwPanelFactory + : private ::cppu::BaseMutex + , public PanelFactoryInterfaceBase +{ +private: + SwPanelFactory(SwPanelFactory const&) = delete; + SwPanelFactory& operator=(SwPanelFactory const&) = delete; + +public: + SwPanelFactory(); + + // XUIElementFactory + css::uno::Reference SAL_CALL createUIElement( + const OUString& rsResourceURL, + const css::uno::Sequence& 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 SAL_CALL getSupportedServiceNames() override + { return css::uno::Sequence{"com.sun.star.ui.UIElementFactory"}; } +}; + +SwPanelFactory::SwPanelFactory() + : PanelFactoryInterfaceBase(m_aMutex) +{ +} + +Reference SAL_CALL SwPanelFactory::createUIElement ( + const OUString& rsResourceURL, + const css::uno::Sequence& rArguments) +{ + Reference xElement; + + const ::comphelper::NamedValueCollection aArguments (rArguments); + Reference xFrame (aArguments.getOrDefault("Frame", Reference())); + Reference xParentWindow (aArguments.getOrDefault("ParentWindow", Reference())); + const sal_uInt64 nBindingsValue (aArguments.getOrDefault("SfxBindings", sal_uInt64(0))); + SfxBindings* pBindings = reinterpret_cast(nBindingsValue); + + VclPtr pParentWindow = VCLUnoHelper::GetWindow(xParentWindow); + if ( ! xParentWindow.is() || pParentWindow==nullptr) + 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")) + { + VclPtr pPanel = sw::sidebar::PageStylesPanel::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageFormatPanel")) + { + VclPtr pPanel = sw::sidebar::PageFormatPanel::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageHeaderPanel")) + { + VclPtr pPanel = sw::sidebar::PageHeaderPanel::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if(rsResourceURL.endsWith("/PageFooterPanel")) + { + VclPtr pPanel = sw::sidebar::PageFooterPanel::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/WrapPropertyPanel")) + { + VclPtr pPanel = sw::sidebar::WrapPropertyPanel::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/NavigatorPanel")) + { + VclPtr pPanel = SwNavigationPI::Create( pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(0,-1,-1)); + } + else if (rsResourceURL.endsWith("/ManageChangesPanel")) + { + VclPtrInstance pPanel(pParentWindow, xFrame); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, + xFrame, + pPanel, + ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/StylePresetsPanel")) + { + VclPtr pPanel = sw::sidebar::StylePresetsPanel::Create(pParentWindow, xFrame); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, pPanel, ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/ThemePanel")) + { + VclPtr pPanel = sw::sidebar::ThemePanel::Create(pParentWindow, xFrame); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, pPanel, ui::LayoutSize(-1,-1,-1)); + } + else if (rsResourceURL.endsWith("/TableEditPanel")) + { + VclPtr pPanel = sw::sidebar::TableEditPanel::Create(pParentWindow, xFrame, pBindings ); + xElement = sfx2::sidebar::SidebarPanelBase::Create( + rsResourceURL, xFrame, pPanel, 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 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 000000000..46f75cd9a --- /dev/null +++ b/sw/source/uibase/sidebar/TableEditPanel.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sw::sidebar +{ +VclPtr TableEditPanel::Create(vcl::Window* pParent, + const css::uno::Reference& 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 VclPtr::Create(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_xRowHeightEdit->set_sensitive(!bDisabled); + + if (pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt32Item* pItem = static_cast(pState); + if (pItem) + { + long nNewHeight = pItem->GetValue(); + nNewHeight = m_xRowHeightEdit->normalize(nNewHeight); + m_xRowHeightEdit->set_value(nNewHeight, FieldUnit::TWIP); + } + } + else if (eState != SfxItemState::DISABLED) + m_xRowHeightEdit->set_text(""); + + break; + } + case SID_ATTR_TABLE_COLUMN_WIDTH: + { + bool bDisabled = eState == SfxItemState::DISABLED; + m_xColumnWidthEdit->set_sensitive(!bDisabled); + + if (pState && eState >= SfxItemState::DEFAULT) + { + const SfxUInt32Item* pItem = static_cast(pState); + if (pItem) + { + long nNewWidth = pItem->GetValue(); + nNewWidth = m_xColumnWidthEdit->normalize(nNewWidth); + m_xColumnWidthEdit->set_value(nNewWidth, FieldUnit::TWIP); + } + } + else if (eState != SfxItemState::DISABLED) + m_xColumnWidthEdit->set_text(""); + + break; + } + } +} + +TableEditPanel::TableEditPanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + SfxBindings* pBindings) + : PanelLayout(pParent, "TableEditPanel", "modules/swriter/ui/sidebartableedit.ui", rxFrame) + , m_pBindings(pBindings) + , m_xRowHeightEdit( + new SvxRelativeField(m_xBuilder->weld_metric_spin_button("rowheight", FieldUnit::CM))) + , m_xColumnWidthEdit( + new SvxRelativeField(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(); +} + +TableEditPanel::~TableEditPanel() { disposeOnce(); } + +void TableEditPanel::InitRowHeightToolitem() +{ + Link aLink = LINK(this, TableEditPanel, RowHeightMofiyHdl); + m_xRowHeightEdit->connect_value_changed(aLink); + + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric(); + m_xRowHeightEdit->SetFieldUnit(eFieldUnit); + + m_xRowHeightEdit->set_min(MINLAY, FieldUnit::TWIP); + m_xRowHeightEdit->set_max(SAL_MAX_INT32, FieldUnit::TWIP); + + limitWidthForSidebar(*m_xRowHeightEdit); +} + +void TableEditPanel::InitColumnWidthToolitem() +{ + Link aLink = LINK(this, TableEditPanel, ColumnWidthMofiyHdl); + m_xColumnWidthEdit->connect_value_changed(aLink); + + FieldUnit eFieldUnit = SW_MOD()->GetUsrPref(false)->GetMetric(); + m_xColumnWidthEdit->SetFieldUnit(eFieldUnit); + + m_xColumnWidthEdit->set_min(MINLAY, FieldUnit::TWIP); + m_xColumnWidthEdit->set_max(SAL_MAX_INT32, FieldUnit::TWIP); + + limitWidthForSidebar(*m_xColumnWidthEdit); +} + +void TableEditPanel::dispose() +{ + m_xRowHeightEdit.reset(); + m_xColumnWidthEdit.reset(); + + 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(); + + PanelLayout::dispose(); +} + +IMPL_LINK_NOARG(TableEditPanel, RowHeightMofiyHdl, weld::MetricSpinButton&, void) +{ + SwTwips nNewHeight = static_cast( + m_xRowHeightEdit->denormalize(m_xRowHeightEdit->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( + m_xColumnWidthEdit->denormalize(m_xColumnWidthEdit->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 000000000..361e86009 --- /dev/null +++ b/sw/source/uibase/sidebar/TableEditPanel.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_SIDEBAR_TABLEEDITPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_TABLEEDITPANEL_HXX + +#include +#include +#include +#include +#include + +namespace sw +{ +namespace sidebar +{ +class TableEditPanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ + friend class VclPtr; + +public: + static VclPtr Create(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + 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{}; + +private: + TableEditPanel(vcl::Window* pParent, const css::uno::Reference& rxFrame, + SfxBindings* pBindings); + virtual ~TableEditPanel() override; + virtual void dispose() override; + + void InitRowHeightToolitem(); + void InitColumnWidthToolitem(); + + SfxBindings* m_pBindings; + + std::unique_ptr m_xRowHeightEdit; + std::unique_ptr m_xColumnWidthEdit; + std::unique_ptr m_xInsert; + std::unique_ptr m_xInsertDispatch; + std::unique_ptr m_xSelect; + std::unique_ptr m_xSelectDispatch; + std::unique_ptr m_xRowSizing; + std::unique_ptr m_xRowSizingDispatch; + std::unique_ptr m_xColumnSizing; + std::unique_ptr m_xColumnSizingDispatch; + std::unique_ptr m_xDelete; + std::unique_ptr m_xDeleteDispatch; + std::unique_ptr m_xSplitMerge; + std::unique_ptr m_xSplitMergeDispatch; + std::unique_ptr m_xMisc; + std::unique_ptr 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 + +#endif // INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_TABLEEDITPANEL_HXX + +/* 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 000000000..290ca4106 --- /dev/null +++ b/sw/source/uibase/sidebar/ThemePanel.cxx @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#include "ThemePanel.hxx" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +class FontSet +{ +public: + OUString maName; + OUString msMonoFont; + OUString msHeadingFont; + OUString msBaseFont; +}; + +class ColorVariable +{ +public: + long mnIndex; + sal_Int16 mnTintShade; + + ColorVariable() + : mnIndex(-1) + , mnTintShade() + {} + + ColorVariable(long nIndex, sal_Int16 nTintShade) + : mnIndex(nIndex) + , mnTintShade(nTintShade) + {} +}; + +class StyleRedefinition +{ + ColorVariable maVariable; + +public: + OUString maElementName; + +public: + explicit StyleRedefinition(const OUString& aElementName) + : maElementName(aElementName) + {} + + void setColorVariable(ColorVariable aVariable) + { + maVariable = aVariable; + } + + Color getColor(svx::ColorSet const & rColorSet) + { + Color aColor; + if (maVariable.mnIndex > -1) + { + aColor = rColorSet.getColor(maVariable.mnIndex); + aColor.ApplyTintOrShade(maVariable.mnTintShade); + } + else + { + aColor = COL_BLACK; + } + return aColor; + } +}; + +class StyleSet +{ + std::vector maStyles; + +public: + explicit StyleSet() + : maStyles() + {} + + void add(StyleRedefinition const & aRedefinition) + { + maStyles.push_back(aRedefinition); + } + + StyleRedefinition* get(const OUString& aString) + { + for (StyleRedefinition & rStyle : maStyles) + { + if (rStyle.maElementName == aString) + { + return &rStyle; + } + } + return nullptr; + } +}; + +StyleSet setupThemes() +{ + StyleSet aSet; + + { + StyleRedefinition aRedefinition("Heading 1"); + aRedefinition.setColorVariable(ColorVariable(10, -1000)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 2"); + aRedefinition.setColorVariable(ColorVariable(7, -500)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 3"); + aRedefinition.setColorVariable(ColorVariable(5, 0)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 4"); + aRedefinition.setColorVariable(ColorVariable(6, -1000)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 5"); + aRedefinition.setColorVariable(ColorVariable(4, -1500)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 6"); + aRedefinition.setColorVariable(ColorVariable(3, -2500)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 7"); + aRedefinition.setColorVariable(ColorVariable(3, -2500)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 8"); + aRedefinition.setColorVariable(ColorVariable(2, 0)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 9"); + aRedefinition.setColorVariable(ColorVariable(2, 0)); + aSet.add(aRedefinition); + } + + { + StyleRedefinition aRedefinition("Heading 10"); + aRedefinition.setColorVariable(ColorVariable(0, 0)); + aSet.add(aRedefinition); + } + + return aSet; +} + +void changeFont(SwFormat* pFormat, SwDocStyleSheet const * pStyle, FontSet const & rFontSet) +{ + if (pStyle->GetName() != "Default Style" && pFormat->GetAttrSet().GetItem(RES_CHRATR_FONT, false) == nullptr) + { + return; + } + + SvxFontItem aFontItem(pFormat->GetFont(false)); + + FontPitch ePitch = aFontItem.GetPitch(); + + if (ePitch == PITCH_FIXED) + { + aFontItem.SetFamilyName(rFontSet.msMonoFont); + } + else + { + if (pStyle->GetName() == "Heading") + { + aFontItem.SetFamilyName(rFontSet.msHeadingFont); + } + else + { + aFontItem.SetFamilyName(rFontSet.msBaseFont); + } + } + + pFormat->SetFormatAttr(aFontItem); +} + +/*void changeBorder(SwTextFormatColl* pCollection, SwDocStyleSheet* pStyle, StyleSet& rStyleSet) +{ + if (pStyle->GetName() == "Heading") + { + SvxBoxItem aBoxItem(pCollection->GetBox()); + editeng::SvxBorderLine aBorderLine; + aBorderLine.SetWidth(40); //20 = 1pt + aBorderLine.SetColor(rColorSet.mBaseColors[0]); + aBoxItem.SetLine(&aBorderLine, SvxBoxItemLine::BOTTOM); + + pCollection->SetFormatAttr(aBoxItem); + } +}*/ + +void changeColor(SwTextFormatColl* pCollection, svx::ColorSet const & rColorSet, StyleRedefinition* pRedefinition) +{ + Color aColor = pRedefinition->getColor(rColorSet); + + SvxColorItem aColorItem(pCollection->GetColor()); + aColorItem.SetValue(aColor); + pCollection->SetFormatAttr(aColorItem); +} + +std::vector initFontSets() +{ + std::vector aFontSets; + { + FontSet aFontSet; + aFontSet.maName = "Liberation Family"; + aFontSet.msHeadingFont = "Liberation Sans"; + aFontSet.msBaseFont = "Liberation Serif"; + aFontSet.msMonoFont = "Liberation Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "DejaVu Family"; + aFontSet.msHeadingFont = "DejaVu Sans"; + aFontSet.msBaseFont = "DejaVu Serif"; + aFontSet.msMonoFont = "DejaVu Sans Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Croscore Modern"; + aFontSet.msHeadingFont = "Caladea"; + aFontSet.msBaseFont = "Carlito"; + aFontSet.msMonoFont = "Liberation Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Carlito"; + aFontSet.msHeadingFont = "Carlito"; + aFontSet.msBaseFont = "Carlito"; + aFontSet.msMonoFont = "Liberation Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Source Sans Family"; + aFontSet.msHeadingFont = "Source Sans Pro"; + aFontSet.msBaseFont = "Source Sans Pro"; + aFontSet.msMonoFont = "Source Code Pro"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Source Sans Family 2"; + aFontSet.msHeadingFont = "Source Sans Pro"; + aFontSet.msBaseFont = "Source Sans Pro Light"; + aFontSet.msMonoFont = "Source Code Pro"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Libertine Family"; + aFontSet.msHeadingFont = "Linux Biolinum G"; + aFontSet.msBaseFont = "Linux Libertine G"; + aFontSet.msMonoFont = "Liberation Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Open Sans"; + aFontSet.msHeadingFont = "Open Sans"; + aFontSet.msBaseFont = "Open Sans"; + aFontSet.msMonoFont = "Droid Sans Mono"; + aFontSets.push_back(aFontSet); + } + { + FontSet aFontSet; + aFontSet.maName = "Droid Sans"; + aFontSet.msHeadingFont = "Droid Sans"; + aFontSet.msBaseFont = "Droid Sans"; + aFontSet.msMonoFont = "Droid Sans Mono"; + aFontSets.push_back(aFontSet); + } + return aFontSets; +} + +FontSet getFontSet(const OUString& rFontVariant, std::vector& aFontSets) +{ + for (const FontSet & rFontSet : aFontSets) + { + if (rFontSet.maName == rFontVariant) + return rFontSet; + } + return aFontSets[0]; +} + +void applyTheme(SfxStyleSheetBasePool* pPool, const OUString& sFontSetName, const OUString& sColorSetName, + StyleSet& rStyleSet, svx::ColorSets& rColorSets) +{ + SwDocStyleSheet* pStyle; + + std::vector aFontSets = initFontSets(); + FontSet aFontSet = getFontSet(sFontSetName, aFontSets); + + svx::ColorSet aColorSet = rColorSets.getColorSet(sColorSetName); + + pStyle = static_cast(pPool->First(SfxStyleFamily::Para)); + while (pStyle) + { + SwTextFormatColl* pCollection = pStyle->GetCollection(); + + changeFont(pCollection, pStyle, aFontSet); + + StyleRedefinition* pRedefinition = rStyleSet.get(pStyle->GetName()); + + if (pRedefinition) + { + changeColor(pCollection, aColorSet, pRedefinition); + } + + pStyle = static_cast(pPool->Next()); + } + + pStyle = static_cast(pPool->First(SfxStyleFamily::Char)); + while (pStyle) + { + SwCharFormat* pCharFormat = pStyle->GetCharFormat(); + + changeFont(static_cast(pCharFormat), pStyle, aFontSet); + + pStyle = static_cast(pPool->Next()); + } +} + +BitmapEx GenerateColorPreview(const svx::ColorSet& rColorSet) +{ + ScopedVclPtrInstance pVirtualDev(*Application::GetDefaultDevice()); + float fScaleFactor = pVirtualDev->GetDPIScaleFactor(); + long BORDER = 2 * fScaleFactor; + long SIZE = 12 * fScaleFactor; + + Size aSize(BORDER * 7 + SIZE * 6, BORDER * 3 + SIZE * 2); + pVirtualDev->SetOutputSizePixel(aSize); + + long x = BORDER; + long y1 = BORDER; + long y2 = y1 + SIZE + BORDER; + + pVirtualDev->SetLineColor(COL_LIGHTGRAY); + + for (sal_uInt32 i = 0; i < 12; i += 2) + { + pVirtualDev->SetFillColor(rColorSet.getColor(i)); + pVirtualDev->DrawRect(tools::Rectangle(x, y1, x + SIZE, y1 + SIZE)); + + pVirtualDev->SetFillColor(rColorSet.getColor(i + 1)); + pVirtualDev->DrawRect(tools::Rectangle(x, y2, x + SIZE, y2 + SIZE)); + + x += SIZE + BORDER; + } + + return pVirtualDev->GetBitmapEx(Point(), aSize); +} + +} // end anonymous namespace + +namespace sw::sidebar { + +VclPtr ThemePanel::Create (vcl::Window* pParent, + const css::uno::Reference& rxFrame) +{ + if (pParent == nullptr) + throw css::lang::IllegalArgumentException("no parent Window given to PagePropertyPanel::Create", nullptr, 0); + if (!rxFrame.is()) + throw css::lang::IllegalArgumentException("no XFrame given to PagePropertyPanel::Create", nullptr, 1); + + return VclPtr::Create(pParent, rxFrame); +} + +ThemePanel::ThemePanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame) + : PanelLayout(pParent, "ThemePanel", "modules/swriter/ui/sidebartheme.ui", rxFrame) + , mxListBoxFonts(m_xBuilder->weld_tree_view("listbox_fonts")) + , mxValueSetColors(new ValueSet(nullptr)) + , mxValueSetColorsWin(new weld::CustomWeld(*m_xBuilder, "valueset_colors", *mxValueSetColors)) + , mxApplyButton(m_xBuilder->weld_button("apply")) + , maColorSets() +{ + mxValueSetColors->SetColCount(2); + mxValueSetColors->SetLineCount(3); + + mxApplyButton->connect_clicked(LINK(this, ThemePanel, ClickHdl)); + mxListBoxFonts->connect_row_activated(LINK(this, ThemePanel, DoubleClickHdl)); + mxValueSetColors->SetDoubleClickHdl(LINK(this, ThemePanel, DoubleClickValueSetHdl)); + + std::vector aFontSets = initFontSets(); + for (const FontSet & rFontSet : aFontSets) + mxListBoxFonts->append_text(rFontSet.maName); + mxListBoxFonts->set_size_request(-1, mxListBoxFonts->get_height_rows(aFontSets.size())); + + maColorSets.init(); + + const std::vector& aColorSets = maColorSets.getColorSets(); + for (size_t i = 0; i < aColorSets.size(); ++i) + { + const svx::ColorSet& rColorSet = aColorSets[i]; + + const OUString& aName = rColorSet.getName(); + BitmapEx aPreview = GenerateColorPreview(rColorSet); + + sal_uInt16 nId = i + 1; + mxValueSetColors->InsertItem(nId, Image(aPreview), aName); + } + + mxValueSetColors->SetOptimalSize(); + + if (!aColorSets.empty()) + mxValueSetColors->SelectItem(1); // ItemId 1, position 0 +} + +ThemePanel::~ThemePanel() +{ + disposeOnce(); +} + +void ThemePanel::dispose() +{ + mxListBoxFonts.reset(); + mxValueSetColorsWin.reset(); + mxValueSetColors.reset(); + mxApplyButton.reset(); + + PanelLayout::dispose(); +} + +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(SfxObjectShell::Current()); + if (!pDocSh) + return; + + sal_uInt32 nItemId = mxValueSetColors->GetSelectedItemId(); + if (!nItemId) + return; + OUString sEntryFonts = mxListBoxFonts->get_selected_text(); + sal_uInt32 nIndex = nItemId - 1; + OUString sEntryColors = maColorSets.getColorSet(nIndex).getName(); + + StyleSet aStyleSet = setupThemes(); + + applyTheme(pDocSh->GetStyleSheetPool(), sEntryFonts, sEntryColors, aStyleSet, maColorSets); +} + +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 000000000..a050f2d4c --- /dev/null +++ b/sw/source/uibase/sidebar/ThemePanel.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/. + * + */ + +#ifndef INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_THEMEPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_THEMEPANEL_HXX + +#include +#include +#include +#include +#include + +namespace sw::sidebar { + +class ThemePanel : public PanelLayout, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface +{ + friend class VclPtr; +public: + static VclPtr Create(vcl::Window* pParent, + const css::uno::Reference& rxFrame); + + 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: + ThemePanel(vcl::Window* pParent, + const css::uno::Reference& rxFrame); + virtual ~ThemePanel() override; + + virtual void dispose() override; + + std::unique_ptr mxListBoxFonts; + std::unique_ptr mxValueSetColors; + std::unique_ptr mxValueSetColorsWin; + std::unique_ptr mxApplyButton; + + svx::ColorSets maColorSets; + + DECL_LINK(ClickHdl, weld::Button&, void); + DECL_LINK(DoubleClickHdl, weld::TreeView&, bool); + DECL_LINK(DoubleClickValueSetHdl, ValueSet*, void); + void DoubleClickHdl(); + +}; + +} // end of namespace sw::sidebar + +#endif // INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_THEMEPANEL_HXX + +/* 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 000000000..bc64fd8b7 --- /dev/null +++ b/sw/source/uibase/sidebar/WrapPropertyPanel.cxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sw::sidebar { + +VclPtr WrapPropertyPanel::Create ( + vcl::Window* 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 VclPtr::Create( + pParent, + rxFrame, + pBindings); +} + +WrapPropertyPanel::WrapPropertyPanel( + vcl::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame, + SfxBindings* pBindings ) + : PanelLayout(pParent, "WrapPropertyPanel", "modules/swriter/ui/sidebarwrap.ui", rxFrame) + , mpBindings(pBindings) + // spacing + , nTop(0) + , nBottom(0) + , nLeft(0) + , nRight(0) + // resources + , 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() +{ + disposeOnce(); +} + +void WrapPropertyPanel::dispose() +{ + mxSpacingLB.reset(); + + mxWrapOptionsDispatch.reset(); + mxWrapOptions.reset(); + + maSwLRSpacingControl.dispose(); + maSwULSpacingControl.dispose(); + + PanelLayout::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( (nLeft == nRight) && (nTop == nBottom) && (nLeft == nTop) ) + { + sal_Int32 nCount = mxSpacingLB->get_count(); + for (sal_Int32 i = 0; i < nCount; i++) + { + if (mxSpacingLB->get_id(i).toUInt32() == nLeft) + { + mxSpacingLB->set_active(i); + int nCustomEntry = mxSpacingLB->find_text(aCustomEntry); + if (nCustomEntry != -1) + mxSpacingLB->remove(nCustomEntry); + return; + } + } + } + + if (mxSpacingLB->find_text(aCustomEntry) == -1) + mxSpacingLB->append_text(aCustomEntry); + mxSpacingLB->set_active_text(aCustomEntry); +} + +IMPL_LINK(WrapPropertyPanel, SpacingLBHdl, weld::ComboBox&, rBox, void) +{ + sal_uInt16 nVal = rBox.get_active_id().toUInt32(); + + SvxLRSpaceItem aLRItem(nVal, nVal, 0, 0, RES_LR_SPACE); + SvxULSpaceItem aULItem(nVal, nVal, RES_UL_SPACE); + + nTop = nBottom = nLeft = 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) + { + nLeft = pItem->GetLeft(); + nRight = pItem->GetRight(); + + UpdateSpacingLB(); + } + } + } + break; + case SID_ATTR_ULSPACE: + { + if(eState >= SfxItemState::DEFAULT) + { + const SvxULSpaceItem* pItem = dynamic_cast< const SvxULSpaceItem* >(pState); + if(pItem) + { + nTop = pItem->GetUpper(); + 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 000000000..1f4d16d80 --- /dev/null +++ b/sw/source/uibase/sidebar/WrapPropertyPanel.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_SIDEBAR_WRAPPROPERTYPANEL_HXX +#define INCLUDED_SW_SOURCE_UIBASE_SIDEBAR_WRAPPROPERTYPANEL_HXX + +#include +#include +#include +#include +#include + +namespace sw::sidebar { + + class WrapPropertyPanel + : public PanelLayout + , public ::sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface + { + public: + static VclPtr Create( + vcl::Window* 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; + virtual void dispose() override; + + WrapPropertyPanel( + vcl::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rxFrame, + SfxBindings* pBindings ); + private: + SfxBindings* mpBindings; + + //Spacing + sal_uInt16 nTop; + sal_uInt16 nBottom; + sal_uInt16 nLeft; + sal_uInt16 nRight; + + //custom entry + OUString aCustomEntry; + + // Controller Items + ::sfx2::sidebar::ControllerItem maSwLRSpacingControl; + ::sfx2::sidebar::ControllerItem maSwULSpacingControl; + + std::unique_ptr mxWrapOptions; + std::unique_ptr mxWrapOptionsDispatch; + + std::unique_ptr 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/table/chartins.cxx b/sw/source/uibase/table/chartins.cxx new file mode 100644 index 000000000..fd73a71ef --- /dev/null +++ b/sw/source/uibase/table/chartins.cxx @@ -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 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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() ); + tools::Rectangle aObjAbs( pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.TopLeft() ), + pParentWin->OutputToAbsoluteScreenPixel( aObjPixel.BottomRight() ) ); + + tools::Rectangle aDesktop = pParentWin->GetDesktopRectPixel(); + Size aSpace = pParentWin->LogicToPixel(Size(8, 12), MapMode(MapUnit::MapAppFont)); + + bool bLayoutRTL = ::GetActiveView()->GetWrtShell().IsTableRightToLeft(); + 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 both fit, prefer right in RTL mode, left otherwise + 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& rLink ) +{ + SwView *pView = ::GetActiveView(); + + // 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()) + { + uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() ); + if(xMCF.is()) + { + 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 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::makeAny( awt::Point(aDialogPos.getX(),aDialogPos.getY()) ) ); + } + } + } + catch (const uno::Exception&) + { + OSL_FAIL("Chart wizard couldn't be positioned automatically" ); + } + } + + ::svt::DialogClosedListener* pListener = new ::svt::DialogClosedListener(); + pListener->SetDialogClosedLink( rLink ); + css::uno::Reference xListener( pListener ); + + xDialog->startExecuteModal( xListener ); + } + 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 000000000..97e852233 --- /dev/null +++ b/sw/source/uibase/table/swtablerep.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 +#include "tablepg.hxx" + +#include +#include + +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_pTColumns.reset( new TColumn[ m_nColCount + 1 ] ); + SwTwips nStart = 0, + nEnd; + for( sal_uInt16 i = 0; i < m_nAllCols; ++i ) + { + nEnd = rTabCol[ i ] - rTabCol.GetLeft(); + m_pTColumns[ i ].nWidth = nEnd - nStart; + m_pTColumns[ i ].bVisible = !rTabCol.IsHidden(i); + if(!m_pTColumns[ i ].bVisible) + m_nColCount --; + nStart = nEnd; + } + m_pTColumns[ m_nAllCols ].nWidth = rTabCol.GetRight() - rTabCol.GetLeft() - nStart; + m_pTColumns[ m_nAllCols ].bVisible = true; + m_nColCount++; + m_nAllCols++; +} + +SwTableRep::~SwTableRep() +{ +} + +bool SwTableRep::FillTabCols( SwTabCols& rTabCols ) const +{ + long nOldLeft = rTabCols.GetLeft(), + nOldRight = rTabCols.GetRight(); + + bool bSingleLine = false; + + for ( size_t i = 0; i < rTabCols.Count(); ++i ) + if(!m_pTColumns[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 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_pTColumns[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_pTColumns[i].nWidth; + rTabCols[i] = nPos + rTabCols.GetLeft(); + rTabCols.SetHidden( i, !m_pTColumns[i].bVisible ); + rTabCols.SetRight(nLeft + m_pTColumns[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 000000000..ecf9b6dea --- /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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +// Adjust line height (dialogue) +void SwTableFUNC::ColWidthDlg(weld::Window *pParent) +{ + InitTabCols(); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateSwTableWidthDlg(pParent, *this)); + pDlg->Execute(); +} + +// Determine the width +SwTwips SwTableFUNC::GetColWidth(sal_uInt16 nNum) const +{ + SwTwips nWidth = 0; + + if( aCols.Count() > 0 ) + { + if(aCols.Count() == GetColCount()) + { + if(nNum == aCols.Count()) + nWidth = aCols.GetRight() - aCols[nNum-1]; + else + { + if(nNum == 0) + nWidth = aCols[nNum] - aCols.GetLeft(); + else + nWidth = aCols[nNum] - aCols[nNum-1]; + } + } + else + { + SwTwips nRValid = nNum < GetColCount() ? + aCols[GetRightSeparator(nNum)] : + aCols.GetRight(); + SwTwips nLValid = nNum ? + aCols[GetRightSeparator(nNum - 1)] : + aCols.GetLeft(); + nWidth = nRValid - nLValid; + } + } + else + nWidth = aCols.GetRight(); + return nWidth; +} + +SwTwips SwTableFUNC::GetMaxColWidth( sal_uInt16 nNum ) const +{ + OSL_ENSURE(nNum <= 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 ( aCols.Count() > 0 ) + { + if(aCols.Count() != GetColCount()) + bCurrentOnly = true; + SwTwips nWidth = GetColWidth(nNum); + + int nDiff = static_cast(nNewWidth - nWidth); + if( !nNum ) + aCols[ GetRightSeparator(0) ] += nDiff; + else if( nNum < GetColCount() ) + { + if(nDiff < GetColWidth(nNum + 1) - MINLAY) + aCols[ GetRightSeparator(nNum) ] += nDiff; + else + { + int nDiffLeft = nDiff - static_cast(GetColWidth(nNum + 1)) + int(MINLAY); + aCols[ GetRightSeparator(nNum) ] += (nDiff - nDiffLeft); + aCols[ GetRightSeparator(nNum - 1) ] -= nDiffLeft; + } + } + else + aCols[ GetRightSeparator(nNum-1) ] -= nDiff; + } + else + aCols.SetRight( std::min( nNewWidth, aCols.GetRightMax()) ); + + pSh->StartAllAction(); + pSh->SetTabCols( aCols, bCurrentOnly ); + pSh->EndAllAction(); +} + +void SwTableFUNC::InitTabCols() +{ + OSL_ENSURE(pSh, "no Shell"); + + if( pFormat && pSh) + pSh->GetTabCols( aCols ); +} + +SwTableFUNC::SwTableFUNC(SwWrtShell *pShell) + : pFormat(pShell->GetTableFormat()), + 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 = pSh->GetTableFormat(); + if ( pFormat2 && pSh->HasOLEObj( pFormat2->GetName() ) ) + { + pSh->StartAllAction(); + pSh->UpdateCharts( pFormat2->GetName() ); + 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; + pSh->StartUndo( SwUndoId::UI_INSERT_CHART ); + pSh->StartAllAction(); + + OUString aName; + if (pSh->IsCursorInTable()) + { + aName = pSh->GetTableFormat()->GetName(); + // insert node before table + pSh->MoveTable( GotoCurrTable, fnTableStart ); + pSh->Up( false ); + if ( pSh->IsCursorInTable() ) + { + if ( aName != pSh->GetTableFormat()->GetName() ) + pSh->Down( false ); // two adjacent tables + } + 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; + 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 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()) + pSh->SetChartName( aName ); + } + pSh->EndAllAction(); + + if (xObj.is() && !comphelper::LibreOfficeKit::isActive()) + { + // Let the chart be activated after the inserting (unless + // via LibreOfficeKit) + SfxInPlaceClient* pClient = pSh->GetView().FindIPClient( xObj, &pSh->GetView().GetEditWin() ); + if ( !pClient ) + { + pClient = new SwOleClient( &pSh->GetView(), &pSh->GetView().GetEditWin(), aEmbObjRef ); + pSh->SetCheckForOLEInCaption( true ); + } + pSh->CalcAndSetScale( aEmbObjRef ); + //#50270# We don't need to handle errors, + //this does the DoVerb in the SfxViewShell. + ErrCode 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( 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( 4 ); + aArgs[0] = beans::PropertyValue( + "CellRangeRepresentation", -1, + uno::makeAny( rCellRange ), beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + "HasCategories", -1, + uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + "FirstCellAsLabel", -1, + uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = beans::PropertyValue( + "DataRowSource", -1, + uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE ); + xDataReceiver->setArguments( aArgs ); + } + + 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 = pSh->GetCurTabColNum(); + size_t nCount = 0; + for( size_t i = 0; i < nPos; i++ ) + if(aCols.IsHidden(i)) + nCount ++; + return nPos - nCount; +} + +sal_uInt16 SwTableFUNC::GetColCount() const +{ + size_t nCount = 0; + for(size_t i = 0; i < aCols.Count(); i++ ) + if(aCols.IsHidden(i)) + nCount ++; + return aCols.Count() - nCount; +} + +int SwTableFUNC::GetRightSeparator(int nNum) const +{ + OSL_ENSURE( nNum < static_cast(GetColCount()) ,"Index out of range"); + int i = 0; + while( nNum >= 0 ) + { + if( !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 000000000..f2a6311fb --- /dev/null +++ b/sw/source/uibase/table/tablepg.hxx @@ -0,0 +1,183 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_TABLE_TABLEPG_HXX +#define INCLUDED_SW_SOURCE_UIBASE_TABLE_TABLEPG_HXX +#include +#include +#include +#include + +class SwWrtShell; +class SwTableRep; +struct ImplSVEvent; + +struct TColumn +{ + SwTwips nWidth; + bool bVisible; +}; + +class SwFormatTablePage : public SfxTabPage +{ + SwTableRep* pTableData; + SwTwips nSaveWidth; + SwTwips nMinTableWidth; + bool bModified; + bool bFull:1; + bool bHtmlMode : 1; + + std::unique_ptr m_xNameED; + std::unique_ptr m_xWidthFT; + std::unique_ptr m_xWidthMF; + std::unique_ptr m_xRelWidthCB; + + std::unique_ptr m_xFullBtn; + std::unique_ptr m_xLeftBtn; + std::unique_ptr m_xFromLeftBtn; + std::unique_ptr m_xRightBtn; + std::unique_ptr m_xCenterBtn; + std::unique_ptr m_xFreeBtn; + + std::unique_ptr m_xLeftFT; + std::unique_ptr m_xLeftMF; + std::unique_ptr m_xRightFT; + std::unique_ptr m_xRightMF; + std::unique_ptr m_xTopFT; + std::unique_ptr m_xTopMF; + std::unique_ptr m_xBottomFT; + std::unique_ptr m_xBottomMF; + + std::unique_ptr m_xTextDirectionLB; + std::unique_ptr m_xProperties; + + void Init(); + void ModifyHdl(const weld::MetricSpinButton& rEdit); + + DECL_LINK(AutoClickHdl, weld::ToggleButton&, void); + DECL_LINK(RelWidthClickHdl, weld::ToggleButton&, void); + void RightModify(); + DECL_LINK(ValueChangedHdl, weld::MetricSpinButton&, void); + +public: + SwFormatTablePage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ); + static std::unique_ptr 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 6 //Number of the used MetricFields + +class SwTableColumnPage : public SfxTabPage +{ + SwTableRep* m_pTableData; + 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 m_aTextArr[MET_FIELDS]; + std::unique_ptr m_xModifyTableCB; + std::unique_ptr m_xProportionalCB; + std::unique_ptr m_xSpaceFT; + std::unique_ptr m_xSpaceED; + std::unique_ptr m_xUpBtn; + std::unique_ptr 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::ToggleButton&, 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 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* pShell; + bool bPageBreak; + bool bHtmlMode; + + std::unique_ptr m_xPgBrkCB; + std::unique_ptr m_xPgBrkRB; + std::unique_ptr m_xColBrkRB; + std::unique_ptr m_xPgBrkBeforeRB; + std::unique_ptr m_xPgBrkAfterRB; + std::unique_ptr m_xPageCollCB; + std::unique_ptr m_xPageCollLB; + std::unique_ptr m_xPageNoCB; + std::unique_ptr m_xPageNoNF; + std::unique_ptr m_xSplitCB; + std::unique_ptr m_xSplitRowCB; + std::unique_ptr m_xKeepCB; + std::unique_ptr m_xHeadLineCB; + std::unique_ptr m_xRepeatHeaderCombo; + std::unique_ptr m_xRepeatHeaderNF; + std::unique_ptr m_xTextDirectionLB; + std::unique_ptr m_xVertOrientLB; + + DECL_LINK(PageBreakHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(ApplyCollClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(PageBreakPosHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(PageBreakTypeHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(PageNoClickHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(SplitHdl_Impl, weld::ToggleButton&, void); + DECL_LINK(HeadLineCBClickHdl, weld::ToggleButton&, void); + +public: + SwTextFlowPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet); + static std::unique_ptr 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(); +}; + +#endif + +/* 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 000000000..7f922dc9c --- /dev/null +++ b/sw/source/uibase/uitest/uiobject.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/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +SwEditWinUIObject::SwEditWinUIObject(const VclPtr& xEditWin): + WindowUIObject(xEditWin), + mxEditWin(xEditWin) +{ +} + +namespace { + +SwWrtShell& getWrtShell(VclPtr 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); + + 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; + sal_Int32 nStartPos = aStartPos.toInt32(); + + itr = rParameters.find("END_POS"); + assert(itr != rParameters.end()); + OUString aEndPos = itr->second; + sal_Int32 nEndPos = aEndPos.toInt32(); + + getWrtShell(mxEditWin).SelectText(nStartPos, nEndPos); + } + } + 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 SwEditWinUIObject::create(vcl::Window* pWindow) +{ + SwEditWin* pEditWin = dynamic_cast(pWindow); + assert(pEditWin); + return std::unique_ptr(new SwEditWinUIObject(pEditWin)); +} + +SwNavigationPIUIObject::SwNavigationPIUIObject(const VclPtr& xSwNavigationPI): + WindowUIObject(xSwNavigationPI), + mxSwNavigationPI(xSwNavigationPI) +{ +} + +StringMap SwNavigationPIUIObject::get_state() +{ + StringMap aMap = WindowUIObject::get_state(); + + aMap["selectioncount"] = OUString::number(mxSwNavigationPI->m_xContentTree->count_selected_rows()); + aMap["selectedtext"] = mxSwNavigationPI->m_xContentTree->get_selected_text(); + + return aMap; +} + +void SwNavigationPIUIObject::execute(const OUString& rAction, + const StringMap& rParameters) +{ + if (rAction == "ROOT") + { + mxSwNavigationPI->m_xContentTree->grab_focus(); + mxSwNavigationPI->ToolBoxSelectHdl("root"); + } + else + WindowUIObject::execute(rAction, rParameters); +} + +std::unique_ptr SwNavigationPIUIObject::create(vcl::Window* pWindow) +{ + SwNavigationPI* pSwNavigationPI = dynamic_cast(pWindow); + assert(pSwNavigationPI); + return std::unique_ptr(new SwNavigationPIUIObject(pSwNavigationPI)); +} + +OUString SwNavigationPIUIObject::get_name() const +{ + return "SwNavigationPIUIObject"; +} + + +/* 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 000000000..e9268bffa --- /dev/null +++ b/sw/source/uibase/uiview/formatclipboard.cxx @@ -0,0 +1,593 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +std::unique_ptr lcl_CreateEmptyItemSet( SelectionType nSelectionType, SfxItemPool& rPool, bool bNoParagraphFormats = false ) +{ + std::unique_ptr pItemSet; + if( nSelectionType & (SelectionType::Frame | SelectionType::Ole | SelectionType::Graphic) ) + { + pItemSet = std::make_unique( + rPool, + svl::Items< + 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>{}); + } + else if( nSelectionType & SelectionType::DrawObject ) + { + //is handled different + } + else if( nSelectionType & SelectionType::Text ) + { + if( bNoParagraphFormats ) + pItemSet = std::make_unique(rPool, + svl::Items{}); + else + pItemSet = std::make_unique( + rPool, + svl::Items< + 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>{}); + } + return pItemSet; +} + +void lcl_getTableAttributes( SfxItemSet& rSet, SwWrtShell &rSh ) +{ + std::unique_ptr aBrush(std::make_unique(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 aBoxDirection(std::make_unique(SvxFrameDirection::Environment, RES_FRAMEDIR)); + if(rSh.GetBoxDirection( aBoxDirection )) + { + aBoxDirection->SetWhich(FN_TABLE_BOX_TEXTORIENTATION); + rSet.Put(*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 pSplit = rSh.GetRowSplit(); + if(pSplit) + rSet.Put(std::move(pSplit)); +} + +void lcl_setTableAttributes( const SfxItemSet& rSet, SwWrtShell &rSh ) +{ + const SfxPoolItem* pItem = nullptr; + bool bBorder = ( SfxItemState::SET == rSet.GetItemState( RES_BOX ) || + SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER ) ); + bool bBackground = SfxItemState::SET == rSet.GetItemState( RES_BACKGROUND, false, &pItem ); + const SfxPoolItem* pRowItem = nullptr, *pTableItem = nullptr; + bBackground |= SfxItemState::SET == rSet.GetItemState( SID_ATTR_BRUSH_ROW, false, &pRowItem ); + bBackground |= SfxItemState::SET == rSet.GetItemState( SID_ATTR_BRUSH_TABLE, false, &pTableItem ); + + if(bBackground) + { + if(pItem) + rSh.SetBoxBackground( *static_cast(pItem) ); + if(pRowItem) + { + std::unique_ptr aBrush(static_cast(pRowItem->Clone())); + aBrush->SetWhich(RES_BACKGROUND); + rSh.SetRowBackground(*aBrush); + } + if(pTableItem) + { + std::unique_ptr aBrush(static_cast(pTableItem->Clone())); + aBrush->SetWhich(RES_BACKGROUND); + rSh.SetTabBackground(*aBrush); + } + } + if(bBorder) + rSh.SetTabBorders( rSet ); + + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_TABLE_HEADLINE, false, &pItem) ) + rSh.SetRowsToRepeat( static_cast(pItem)->GetValue() ); + + SwFrameFormat* pFrameFormat = rSh.GetTableFormat(); + if(pFrameFormat) + { + //RES_SHADOW + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_SHADOW), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + + //RES_BREAK + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_BREAK), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + + //RES_PAGEDESC + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_PAGEDESC), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + + //RES_LAYOUT_SPLIT + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_LAYOUT_SPLIT), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + + //RES_KEEP + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_KEEP), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + + //RES_FRAMEDIR + pItem=nullptr; + rSet.GetItemState(rSet.GetPool()->GetWhich(RES_FRAMEDIR), false, &pItem); + if(pItem) + pFrameFormat->SetFormatAttr( *pItem ); + } + + if( SfxItemState::SET == rSet.GetItemState( FN_TABLE_BOX_TEXTORIENTATION, false, &pItem) ) + { + SvxFrameDirectionItem aDirection( SvxFrameDirection::Environment, RES_FRAMEDIR ); + aDirection.SetValue(static_cast< const SvxFrameDirectionItem* >(pItem)->GetValue()); + rSh.SetBoxDirection(aDirection); + } + + if( SfxItemState::SET == rSet.GetItemState( FN_TABLE_SET_VERT_ALIGN, false, &pItem)) + rSh.SetBoxAlign(static_cast(pItem)->GetValue()); + + if( SfxItemState::SET == rSet.GetItemState( RES_ROW_SPLIT, false, &pItem) ) + rSh.SetRowSplit(*static_cast(pItem)); +} +}//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()->nContent == 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( 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( + rPool, + svl::Items< + 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>{}); + 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 sal_uInt16* pRanges = rStyleAttrSet.GetRanges(); + while( *pRanges ) + { + for ( sal_uInt16 nWhich = *pRanges; nWhich <= *(pRanges+1); ++nWhich ) + { + const SfxPoolItem* pItem; + if( SfxItemState::SET == rStyleAttrSet.GetItemState( nWhich, false, &pItem ) ) + { + rItemVector.emplace_back( pItem->Clone() ); + } + } + pRanges += 2; + } +} +// 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( 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(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 pragraph format in the pool + SwDocStyleSheet* pStyle = static_cast(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 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 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 000000000..fae7d9cef --- /dev/null +++ b/sw/source/uibase/uiview/pview.cxx @@ -0,0 +1,1887 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "viewfunc.hxx" + +#include +#include +#include + +#define ShellClass_SwPagePreview +#include +#include +#include + +#include + +#include +#include +#include + +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(SAL_N_ELEMENTS(aZoomArr)); + if (bZoomIn) + { + for(int i = nZoomArrSize - 1; i >= 0; --i) + { + if(nCurrentZoom > aZoomArr[i] || !i) + return aZoomArr[i]; + } + } + else + { + for(sal_uInt16 i : aZoomArr) + { + if(nCurrentZoom < i) + return 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 m_xRowEdit; + std::unique_ptr 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(sal_uInt8(m_xRowEdit->get_value()), sal_uInt8(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) +{ + SetOutDevViewType( OutDevViewType::PrintPreview ); + SetHelpId(HID_PAGEPREVIEW); + SetFillColor( GetBackground().GetColor() ); + 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_uInt8 nNewRow, sal_uInt8 nNewCol ) +{ + if( !mpViewShell || !mpViewShell->GetLayout() ) + return; + + const sal_uInt8 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: + // and 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(mnSttPage, 1); + + OUStringBuffer aStatusStr; + const sal_uInt16 nVirtPageNum = mpPgPreviewLayout->GetVirtPageNumByPageNum( nPageNum ); + if( nVirtPageNum && nVirtPageNum != nPageNum ) + { + aStatusStr.append( OUString::number(nVirtPageNum) ).append( " " ); + } + aStatusStr.append( OUString::number(nPageNum) ).append( " / " ).append( OUString::number(nPageCnt) ); + return aStatusStr.makeStringAndClear(); +} + +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_OUT; break; + case KEY_ESCAPE: nSlot = FN_CLOSE_PAGEPREVIEW; break; + case KEY_SUBTRACT : nSlot = SID_ZOOM_IN; 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() ) ) + { + 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 *pTmpFrame = mrView.GetViewFrame(); + pTmpFrame->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_uInt8 nRow, sal_uInt8 nCol ) +{ + SwMasterUsrPref *pOpt = const_cast(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->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->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_uInt8 nRow = 1; + bool bRefresh = true; + + switch(rReq.GetSlot()) + { + case FN_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_uInt8 nCols = static_cast(pArgs->Get(SID_ATTR_TABLE_COLUMN).GetValue()); + sal_uInt8 nRows = static_cast(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(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(); + const SfxPoolItem* pItem; + ScopedVclPtr pDlg; + if(!pArgs) + { + SfxItemSet aCoreSet(GetPool(), svl::Items{}); + 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()->GetWindow().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(SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOM, true, &pItem)) + { + eType = static_cast(pItem)->GetType(); + nZoomFactor = static_cast(pItem)->GetValue(); + } + else if(SfxItemState::SET == pArgs->GetItemState(FN_PREVIEW_ZOOM, true, &pItem)) + nZoomFactor = static_cast(pItem)->GetValue(); + if(USHRT_MAX != nZoomFactor) + SetZoom(eType, nZoomFactor); + } + } + break; + case SID_ATTR_ZOOMSLIDER : + { + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + + if ( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOMSLIDER, true, &pItem ) ) + { + const sal_uInt16 nCurrentZoom = static_cast(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: + { + sal_uInt16 nPageNum = 1; + const SfxItemSet *pArgs = rReq.GetArgs(); + if( pArgs && pArgs->Count()) + { + nPageNum = static_cast(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 *pTmpFrame = GetViewFrame(); + pTmpFrame->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: + { + OUString aStr = m_sPageStr + m_pViewWin->GetStatusStr( mnPageCount ); + rSet.Put( SfxStringItem( nWhich, aStr) ); + } + 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_OUT == nWhich && pVOpt->GetZoom() >= MAX_PREVIEW_ZOOM)|| + (SID_ZOOM_IN == nWhich && pVOpt->GetZoom() <= MIN_PREVIEW_ZOOM)) + { + rSet.DisableItem(nWhich); + } + } + 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; + SfxItemSet aSet( *rSet.GetPool(), svl::Items{} ); + GetSlotState( SID_PRINTDOC, SfxViewShell::GetInterface(), &aSet ); + if( SfxItemState::DISABLED == aSet.GetItemState( SID_PRINTDOC, + false, &pItem )) + rSet.DisableItem( nWhich ); + else if( SfxItemState::SET == aSet.GetItemState( SID_PRINTDOC, + false, &pItem )) + { + const_cast(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(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 ); + GetViewShell()->ApplyAccessibilityOptions(SW_MOD()->GetAccessibilityOptions()); + + // 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 *pViewFrame, SfxViewShell* pOldSh): + SfxViewShell( pViewFrame, SWVIEWFLAGS ), + m_pViewWin( VclPtr::Create(&GetViewFrame()->GetWindow(), *this ) ), + m_nNewPage(USHRT_MAX), + m_sPageStr(SwResId(STR_PAGE)), + m_pHScrollbar(nullptr), + m_pVScrollbar(nullptr), + m_pScrollFill(VclPtr::Create( &pViewFrame->GetWindow(), WB_SIZEABLE )), + mnPageCount( 0 ), + mbResetFormDesignMode( false ), + mbFormDesignModeToReset( false ) +{ + SetName("PageView"); + SetWindow( m_pViewWin ); + CreateScrollbar( true ); + CreateScrollbar( false ); + + //notify notebookbar change in context + SfxShell::SetContextBroadcasterEnabled(true); + SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Printpreview)); + SfxShell::BroadcastContextForActivation(true); + //removelisteners for notebookbar + if (auto& pBar = SfxViewFrame::Current()->GetWindow().GetSystemWindow()->GetNotebookBar()) + pBar->ControlListenerForCurrentController(false); + + SfxObjectShell* pObjShell = pViewFrame->GetObjectShell(); + if ( !pOldSh ) + { + // Exists already a view on the document? + SfxViewFrame *pF = SfxViewFrame::GetFirst( pObjShell ); + if ( pF == pViewFrame ) + pF = SfxViewFrame::GetNext( *pF, pObjShell ); + if ( pF ) + pOldSh = pF->GetViewShell(); + } + + SwViewShell *pVS, *pNew; + + if (SwPagePreview* pPagePreview = dynamic_cast(pOldSh)) + pVS = pPagePreview->GetViewShell(); + else + { + if (SwView* pView = dynamic_cast(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(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(pViewFrame->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(); + if (SfxViewFrame* pCurrent = SfxViewFrame::Current()) + if (auto& pBar = pCurrent->GetWindow().GetSystemWindow()->GetNotebookBar()) + pBar->ControlListenerForCurrentController(true); // start listening now + m_pScrollFill.disposeAndClear(); + m_pHScrollbar.disposeAndClear(); + m_pVScrollbar.disposeAndClear(); +} + +SwDocShell* SwPagePreview::GetDocShell() +{ + return dynamic_cast( GetViewFrame()->GetObjectShell() ); +} + +void SwPagePreview::CreateScrollbar( bool bHori ) +{ + vcl::Window *pMDI = &GetViewFrame()->GetWindow(); + VclPtr& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar; + + assert(!ppScrollbar); //check beforehand! + + ppScrollbar = VclPtr::Create( pMDI, bHori ); + + ScrollDocSzChg(); + ppScrollbar->EnableDrag(); + ppScrollbar->SetEndScrollHdl( LINK( this, SwPagePreview, EndScrollHdl )); + + ppScrollbar->SetScrollHdl( LINK( this, SwPagePreview, ScrollHdl )); + + 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 + OUString aStr = m_sPageStr + m_pViewWin->GetStatusStr( mnPageCount ); + 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 ); + } + rBindings.SetState( SfxStringItem( FN_STAT_PAGE, aStr ) ); + } + return bChg; +} + +// From here, everything was taken from the SwView. +void SwPagePreview::CalcAndSetBorderPixel( SvBorder &rToFill ) +{ + const StyleSettings &rSet = m_pViewWin->GetSettings().GetStyleSettings(); + const long nTmp = rSet.GetScrollBarSize(); + if ( m_pVScrollbar->IsVisible( true ) ) + rToFill.Right() = nTmp; + if ( m_pHScrollbar->IsVisible( 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, aRect.TopLeft(), aRect.GetSize(), + m_pViewWin->GetOutputSizePixel(), + *m_pVScrollbar, *m_pHScrollbar, *m_pScrollFill ); + + // 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, rOfst, rSize, m_pViewWin->GetOutputSizePixel(), + *m_pVScrollbar, *m_pHScrollbar, *m_pScrollFill ); +} + +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, ScrollHdl, ScrollBar *, p, void ) +{ + SwScrollbar* pScrollbar = static_cast(p); + if(!GetViewShell()) + return; + if( !pScrollbar->IsHoriScroll() && + pScrollbar->GetType() == ScrollType::Drag && + Help::IsQuickHelpEnabled() && + GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow()) + { + // Scroll how many pages?? + OUString sStateStr(m_sPageStr); + long nThmbPos = pScrollbar->GetThumbPos(); + if( 1 == m_pViewWin->GetCol() || !nThmbPos ) + ++nThmbPos; + sStateStr += OUString::number( nThmbPos ); + Point aPos = pScrollbar->GetParent()->OutputToScreenPixel( + pScrollbar->GetPosPixel()); + aPos.setY( pScrollbar->OutputToScreenPixel(pScrollbar->GetPointerPosPixel()).Y() ); + tools::Rectangle aRect; + aRect.SetLeft( aPos.X() -8 ); + aRect.SetRight( aRect.Left() ); + aRect.SetTop( aPos.Y() ); + aRect.SetBottom( aRect.Top() ); + + Help::ShowQuickHelp(pScrollbar, aRect, sStateStr, + QuickHelpFlags::Right|QuickHelpFlags::VCenter); + + } + else + EndScrollHdl( pScrollbar ); +} + +IMPL_LINK( SwPagePreview, EndScrollHdl, ScrollBar *, p, void ) +{ + SwScrollbar* pScrollbar = static_cast(p); + if(!GetViewShell()) + return; + + // boolean to avoid unnecessary invalidation of the window. + bool bInvalidateWin = true; + + if( !pScrollbar->IsHoriScroll() ) // scroll vertically + { + if ( Help::IsQuickHelpEnabled() ) + Help::ShowQuickHelp(pScrollbar, tools::Rectangle(), OUString()); + if ( GetViewShell()->PagePreviewLayout()->DoesPreviewLayoutRowsFitIntoWindow() ) + { + // Scroll how many pages ?? + const sal_uInt16 nThmbPos = static_cast(pScrollbar->GetThumbPos()); + // adjust to new preview functionality + if( nThmbPos != m_pViewWin->SelectedPage() ) + { + // consider case that page + // 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 + { + long nThmbPos = pScrollbar->GetThumbPos(); + m_pViewWin->Scroll(0, nThmbPos - m_pViewWin->GetPaintedPreviewDocRect().Top()); + } + } + else + { + long nThmbPos = pScrollbar->GetThumbPos(); + 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()) ; + 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; + + long nVisWidth = rDocRect.GetWidth(); + 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); + } + m_pScrollFill->Show(bShowVScrollbar && 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(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 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(long nXMove, 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!!! + + 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); + } + return GetAccessible( false ); +} + +void SwPagePreview::ApplyAccessibilityOptions(SvtAccessibilityOptions const & rAccessibilityOptions) +{ + GetViewShell()->ApplyAccessibilityOptions(rAccessibilityOptions); +} + +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 000000000..e44154b34 --- /dev/null +++ b/sw/source/uibase/uiview/scroll.cxx @@ -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 . + */ + +#include + +#define SCROLL_LINE_SIZE 250 + +SwScrollbar::SwScrollbar( vcl::Window *pWin, bool bHoriz ) : + ScrollBar( pWin, + WinBits( WB_3DLOOK | WB_HIDE | ( bHoriz ? WB_HSCROLL : WB_VSCROLL) ) ), + bHori( bHoriz ), + bAuto( false ), + bVisible(false), + bSizeSet(false) +{ + // No mirroring for horizontal scrollbars + if( bHoriz ) + EnableRTL( false ); +} + + SwScrollbar::~SwScrollbar() {} + +// Will be called after a change of the document size +// to refresh the range of the scrollbars. + +void SwScrollbar::DocSzChgd( const Size &rSize ) +{ + aDocSz = rSize; + SetRange( Range( 0, bHori ? rSize.Width() : rSize.Height()) ); + const sal_uLong 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 ) +{ + long nThumb, nVisible; + if( bHori ) + { + nThumb = rRect.Left(); + nVisible = rRect.GetWidth(); + } + else + { + nThumb = rRect.Top(); + nVisible = rRect.GetHeight(); + } + + SetVisibleSize( nVisible ); + DocSzChgd(aDocSz); + SetThumbPos( nThumb ); + if(bAuto) + AutoShow(); +} + +void SwScrollbar::ExtendedShow( bool bSet ) +{ + bVisible = bSet; + if( (!bSet || !bAuto) && IsUpdateMode() && bSizeSet) + ScrollBar::Show(bSet); +} + +void SwScrollbar::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize ) +{ + ScrollBar::SetPosSizePixel(rNewPos, rNewSize); + bSizeSet = true; + if(bVisible) + ExtendedShow(); + +} + +void SwScrollbar::SetAuto(bool bSet) +{ + if(bAuto != bSet) + { + bAuto = bSet; + + // hide automatically - then show + if(!bAuto && bVisible && !ScrollBar::IsVisible()) + ExtendedShow(); + else if(bAuto) + AutoShow(); // or hide automatically + } +} + +void SwScrollbar::AutoShow() +{ + long nVis = GetVisibleSize(); + long nLen = GetRange().Len(); + if( nVis >= nLen - 1) + { + if(ScrollBar::IsVisible()) + ScrollBar::Show(false); + } + else if ( !ScrollBar::IsVisible() ) + { + ScrollBar::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 000000000..0c3aaa4a3 --- /dev/null +++ b/sw/source/uibase/uiview/srcview.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "viewfunc.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#define ShellClass_SwSrcView +#include + +#include +#include + +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 ); + + long nFontHeight = rOutDev.GetTextHeight(); + + // 1.Border => Line, 2+3 Border = Space. + long nYTop = TMARGPRN-3*nBorder-nFontHeight; + + long nXLeft = nLeftMargin-nBorder; + long nXRight = aSz.Width()-RMARGPRN+nBorder; + + rOutDev.DrawRect( tools::Rectangle( + Point( nXLeft, nYTop ), + Size( nXRight-nXLeft, aSz.Height() - nYTop - BMARGPRN + nBorder ) ) ); + + 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) + { + SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); + const char *pCharSet = + rtl_getBestMimeCharsetFromTextEncoding( rHtmlOptions.GetTextEncoding() ); + eRet = rtl_getTextEncodingFromMimeCharset( pCharSet ); + } + 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, OUString(aPadSpaces, nPadLen)); + nPos += nPadLen; + } + return aRet; +} + +SwSrcView::SwSrcView(SfxViewFrame* pViewFrame, SfxViewShell*) : + SfxViewShell( pViewFrame, SWSRCVIEWFLAGS ), + aEditWin( VclPtr::Create( &pViewFrame->GetWindow(), this ) ), + bSourceSaved(false), + eLoadEncoding(RTL_TEXTENCODING_DONTKNOW) +{ + Init(); +} + +SwSrcView::~SwSrcView() +{ + SwDocShell* pDocShell = GetDocShell(); + OSL_ENSURE(dynamic_cast( pDocShell), "Why no WebDocShell?" ); + const TextSelection& rSel = aEditWin->GetTextView()->GetSelection(); + static_cast(pDocShell)->SetSourcePara( static_cast< sal_uInt16 >( rSel.GetStart().GetPara() ) ); + + uno::Reference xDPS( + pDocShell->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference xDocProps + = xDPS->getDocumentProperties(); + OUString url = xDocProps->getAutoloadURL(); + sal_Int32 delay = xDocProps->getAutoloadSecs(); + pDocShell->SetAutoLoad(INetURLObject(url), delay, + (delay != 0) || !url.isEmpty()); + EndListening(*pDocShell); + pSearchItem.reset(); + + aEditWin.disposeAndClear(); +} + +void SwSrcView::SaveContentTo(SfxMedium& rMed) +{ + SvStream* pOutStream = rMed.GetOutStream(); + pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(eLoadEncoding)); + aEditWin->Write( *pOutStream ); +} + +void SwSrcView::Init() +{ + SetName("Source"); + SetWindow( 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 + { + aEditWin->SetReadonly(true); + } + + SetNewWindowAllowed( false ); + StartListening(*pDocShell, DuplicateHandling::Prevent); +} + +SwDocShell* SwSrcView::GetDocShell() +{ + SfxObjectShell* pObjShell = GetViewFrame()->GetObjectShell(); + return dynamic_cast( pObjShell ); +} + +void SwSrcView::SaveContent(const OUString& rTmpFile) +{ + SfxMedium aMedium( rTmpFile, StreamMode::WRITE); + SvStream* pOutStream = aMedium.GetOutStream(); + pOutStream->SetStreamCharSet( lcl_GetStreamCharSet(eLoadEncoding) ); + aEditWin->Write(*pOutStream); + aMedium.Commit(); +} + +void SwSrcView::Execute(SfxRequest& rReq) +{ + TextView* pTextView = aEditWin->GetTextView(); + switch( rReq.GetSlot() ) + { + case SID_SAVEACOPY: + case SID_SAVEASDOC: + { + SvtPathOptions aPathOpt; + // filesave dialog with autoextension + FileDialogHelper aDlgHelper( + TemplateDescription::FILESAVE_AUTOEXTENSION, + FileDialogFlags::NONE, aEditWin->GetFrameWeld()); + uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + // search for an html filter for export + SfxFilterContainer* pFilterCont = GetObjectShell()->GetFactory().GetFilterContainer(); + std::shared_ptr 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 ) ; + } + + xFP->setDisplayDirectory( aPathOpt.GetWorkPath() ); + if( aDlgHelper.Execute() == ERRCODE_NONE) + { + SfxMedium aMedium( xFP->getSelectedFiles().getConstArray()[0], + StreamMode::WRITE | StreamMode::SHARE_DENYNONE ); + SvStream* pOutStream = aMedium.GetOutStream(); + pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(eLoadEncoding)); + 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 SfxBoolItem* pItem = static_cast(pDocShell->ExecuteSlot(rReq, pDocShell->GetInterface())); + if(pItem && pItem->GetValue()) + pMed = pDocShell->GetMedium(); + } + if(pMed) + { + SvStream* pOutStream = pMed->GetOutStream(); + pOutStream->Seek(0); + pOutStream->SetStreamSize(0); + pOutStream->SetStreamCharSet(lcl_GetStreamCharSet(eLoadEncoding)); + aEditWin->Write( *pOutStream ); + pMed->CloseOutStream(); + pMed->Commit(); + pDocShell->GetDoc()->getIDocumentState().ResetModified(); + bSourceSaved = true; + aEditWin->ClearModifyFlag(); + } + } + break; + case FID_SEARCH_NOW: + { + const SfxItemSet* pTmpArgs = rReq.GetArgs(); + + const sal_uInt16 nWhich = pTmpArgs->GetWhichByPos( 0 ); + OSL_ENSURE( nWhich, "Which for SearchItem ?" ); + const SfxPoolItem& rItem = pTmpArgs->Get( nWhich ); + SetSearchItem( static_cast(rItem)); + StartSearchAndReplace( static_cast(rItem), rReq.IsAPI() ); + if(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(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; + } + aEditWin->Invalidate(); +} + +void SwSrcView::GetState(SfxItemSet& rSet) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + TextView* pTextView = 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: + { + OUString aPos( SwResId(STR_SRCVIEW_ROW) ); + TextSelection aSel = pTextView->GetSelection(); + aPos += OUString::number( aSel.GetEnd().GetPara()+1 ); + aPos += " : " + + SwResId(STR_SRCVIEW_COL); + aPos += OUString::number( aSel.GetEnd().GetIndex()+1 ); + SfxStringItem aItem( nWhich, aPos ); + 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(nOpt) ) ); + } + break; + case SID_SEARCH_ITEM: + { + OUString sSelected; + if ( !pTextView->HasSelection() ) + { + const TextSelection& rSel = pTextView->GetSelection(); + sSelected = 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)); + aStr += rMgr.GetUndoActionComment(--nCount); + rSet.Put(SfxStringItem(nWhich, aStr)); + } + else + rSet.DisableItem(nWhich); + } + else + { + nCount = rMgr.GetRedoActionCount(); + if(nCount) + { + OUString aStr(SvtResId( STR_REDO)); + aStr += 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( + aEditWin.get()) ); + bool bDisable = !aDataHelper.GetXTransferable().is() || + 0 == aDataHelper.GetFormatCount(); + if( bDisable ) + rSet.DisableItem(nWhich); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + +SvxSearchItem* SwSrcView::GetSearchItem() +{ + if(!pSearchItem) + { + pSearchItem.reset(new SvxSearchItem(SID_SEARCH_ITEM)); + } + return pSearchItem.get(); +} + +void SwSrcView::SetSearchItem( const SvxSearchItem& rItem ) +{ + pSearchItem.reset(rItem.Clone()); +} + +void SwSrcView::StartSearchAndReplace(const SvxSearchItem& rSearchItem, + bool bApi, + bool bRecursive) +{ + TextView* pTextView = 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 ) + { + bool bNotFoundMessage = false; + if(!bRecursive) + { + bNotFoundMessage = bAtStart; + } + else if(bAtStart) + { + bNotFoundMessage = true; + } + + if(!bApi) + { + if(bNotFoundMessage) + { + std::unique_ptr xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/infonotfounddialog.ui")); + std::unique_ptr xInfoBox(xBuilder->weld_message_dialog("InfoNotFoundDialog")); + xInfoBox->run(); + } + else if(!bRecursive) + { + int nRet; + + if (!bForward) + { + std::unique_ptr xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinueenddialog.ui")); + std::unique_ptr xQueryBox(xBuilder->weld_message_dialog("QueryContinueEndDialog")); + nRet = xQueryBox->run(); + } + else + { + std::unique_ptr xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/querycontinuebegindialog.ui")); + std::unique_ptr 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 = aEditWin->GetTextEngine(); + pOutDev->SetMapMode(MapMode(MapUnit::Map100thMM)); + vcl::Font aFont( aEditWin->GetOutWin()->GetFont() ); + Size aSize( aFont.GetFontSize() ); + aSize = aEditWin->GetOutWin()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM)); + aFont.SetFontSize( aSize ); + aFont.SetColor( COL_BLACK ); + pOutDev->SetFont( aFont ); + + OUString aTitle( GetViewFrame()->GetWindow().GetText() ); + + const long nLineHeight = pOutDev->GetTextHeight(); // slightly more + const 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 long nLinespPage = nLineHeight ? aPaperSz.Height() / nLineHeight : 1; + const long nCharWidth = pOutDev->GetTextWidth("X"); + const sal_Int32 nCharspLine = nCharWidth ? static_cast(aPaperSz.Width() / nCharWidth) : 1; + const sal_uInt32 nParas = pTextEngine->GetParagraphCount(); + + const sal_Int32 nPages = static_cast(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() || !aEditWin->IsReadonly()))) + { + // Broadcast only comes once! + const bool bReadonly = pDocSh->IsReadOnly(); + aEditWin->SetReadonly(bReadonly); + } + } + SfxViewShell::Notify(rBC, rHint); +} + +void SwSrcView::Load(SwDocShell* pDocShell) +{ + SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); + const char *pCharSet = + rtl_getBestMimeCharsetFromTextEncoding( rHtmlOptions.GetTextEncoding() ); + rtl_TextEncoding eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet ); + + aEditWin->SetReadonly(pDocShell->IsReadOnly()); + aEditWin->SetTextEncoding(eDestEnc); + SfxMedium* pMedium = pDocShell->GetMedium(); + + std::shared_ptr 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; + aEditWin->SetTextEncoding(eDestEnc); + } + pStream->SetStreamCharSet( eDestEnc ); + pStream->Seek(0); + TextEngine* pTextEngine = aEditWin->GetTextEngine(); + pTextEngine->EnableUndo(false); + aEditWin->Read(*pStream); + pTextEngine->EnableUndo(true); + } + else + { + vcl::Window& rTmpWindow = GetViewFrame()->GetWindow(); + std::unique_ptr xBox(Application::CreateMessageDialog(rTmpWindow.GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_ERR_SRCSTREAM))); + xBox->run(); + } + } + else + { + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + const OUString sFileURL( aTempFile.GetURL() ); + + { + SfxMedium aMedium( sFileURL,StreamMode::READWRITE ); + SwWriter aWriter( aMedium, *pDocShell->GetDoc() ); + WriterRef xWriter; + ::GetHTMLWriter(OUString(), aMedium.GetBaseURL( true ), xWriter); + const OUString sWriteName = pDocShell->HasName() + ? pMedium->GetName() + : sFileURL; + ErrCode nRes = aWriter.Write(xWriter, &sWriteName); + if(nRes) + { + ErrorHandler::HandleError(nRes); + aEditWin->SetReadonly(true); + } + aMedium.Commit(); + SvStream* pInStream = aMedium.GetInStream(); + pInStream->Seek(0); + pInStream->SetStreamCharSet( eDestEnc ); + + aEditWin->Read(*pInStream); + } + } + aEditWin->ClearModifyFlag(); + + eLoadEncoding = eDestEnc; + + if(bDocModified) + pDocShell->SetModified();// The flag will be reset in between times. + // Disable AutoLoad + pDocShell->SetAutoLoad(INetURLObject(), 0, false); + OSL_ENSURE(dynamic_cast( pDocShell), "Why no WebDocShell?" ); + sal_uInt16 nLine = static_cast(pDocShell)->GetSourcePara(); + aEditWin->SetStartLine(nLine); + aEditWin->GetTextEngine()->ResetUndo(); + 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 000000000..05f5f6ccc --- /dev/null +++ b/sw/source/uibase/uiview/swcli.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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(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( long( aLogRect.GetWidth() / GetScaleWidth() ), + 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(GetViewShell())->GetWrtShell(); + SwRect aFrame( rSh.GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, GetObject() )); + if ( !aFrame.IsOver( 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(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( long(aVisSize.Width() * GetScaleWidth()) ); + aVisSize.setHeight( 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 ); + } +} + +/* 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 000000000..6a45751ad --- /dev/null +++ b/sw/source/uibase/uiview/uivwimp.cxx @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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) + : mxXTextView() + , pView(pShell) + , eShellMode(ShellMode::Text) + , m_nParam(0) + , m_bSelectObject(false) + , m_bEditingPositionSet(false) +{ + mxXTextView = new SwXTextView(pView); + xDisProvInterceptor = new SwXDispatchProviderInterceptor(*pView); +} + +SwView_Impl::~SwView_Impl() +{ + auto pInterceptor = comphelper::getUnoTunnelImplementation(xDisProvInterceptor); + if(pInterceptor) + pInterceptor->Invalidate(); + view::XSelectionSupplier* pTextView = mxXTextView.get(); + static_cast(pTextView)->Invalidate(); + mxXTextView.clear(); + if( mxScanEvtLstnr.is() ) + mxScanEvtLstnr->ViewDestroyed(); + if( mxClipEvtLstnr.is() ) + { + mxClipEvtLstnr->AddRemoveListener( false ); + mxClipEvtLstnr->ViewDestroyed(); + } +#if HAVE_FEATURE_DBCONNECTIVITY + xConfigItem.reset(); +#endif + m_pDocInserter.reset(); + m_pRequest.reset(); +} + +void SwView_Impl::SetShellMode(ShellMode eSet) +{ + eShellMode = eSet; +} + +view::XSelectionSupplier* SwView_Impl::GetUNOObject() +{ + return mxXTextView.get(); +} + +SwXTextView* SwView_Impl::GetUNOObject_Impl() +{ + view::XSelectionSupplier* pTextView = mxXTextView.get(); + return static_cast(pTextView); +} + +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 xInit(xScanMgr, UNO_QUERY); + if (xInit.is()) + { + // initialize dialog + weld::Window* pWindow = rReq.GetFrameWeld(); + uno::Sequence aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", pWindow ? uno::Any(pWindow->GetXWindow()) : uno::Any(Reference())} + })); + 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 xBox(Application::CreateMessageDialog(rReq.GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_SCAN_NOSOURCE))); + xBox->run(); + rReq.Ignore(); + } + else + { + rReq.Done(); + SfxBindings& rBind = pView->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_TWAIN_SELECT ); + rBind.Invalidate( SID_TWAIN_TRANSFER ); + } + } + break; + } +} + +SwScannerEventListener& SwView_Impl::GetScannerEventListener() +{ + if(!mxScanEvtLstnr.is()) + mxScanEvtLstnr = new SwScannerEventListener(*pView); + return *mxScanEvtLstnr; +} + +void SwView_Impl::AddClipboardListener() +{ + if(!mxClipEvtLstnr.is()) + { + mxClipEvtLstnr = new SwClipboardChangeListener( *pView ); + mxClipEvtLstnr->AddRemoveListener( true ); + } +} + +void SwView_Impl::Invalidate() +{ + GetUNOObject_Impl()->Invalidate(); + for (const auto& xTransferable: mxTransferables) + { + auto pTransferable = comphelper::getUnoTunnelImplementation(xTransferable.get()); + if(pTransferable) + pTransferable->Invalidate(); + } +} + +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. + mxTransferables.erase(std::remove_if(mxTransferables.begin(), mxTransferables.end(), + [](const css::uno::WeakReference& rTunnel) { + uno::Reference xTunnel(rTunnel.get(), uno::UNO_QUERY); + return !xTunnel.is(); + }), mxTransferables.end()); + + mxTransferables.emplace_back(uno::Reference(&rTransferable)); + } + osl_atomic_decrement(&rTransferable.m_refCount); +} + +void SwView_Impl::StartDocumentInserter( + const OUString& rFactory, + const Link& 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(pView->GetFrameWeld(), rFactory, mode)); + m_pDocInserter->StartExecuteModal( rEndDialogHdl ); +} + +std::unique_ptr 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( pView ) + pView->ScannerEventHdl(); +#endif +} + +SwClipboardChangeListener::~SwClipboardChangeListener() +{ +} + +void SAL_CALL SwClipboardChangeListener::disposing( const EventObject& /*rEventObject*/ ) +{ +} + +void SAL_CALL SwClipboardChangeListener::changedContents( const css::datatransfer::clipboard::ClipboardEvent& rEventObject ) + +{ + const SolarMutexGuard aGuard; + if( pView ) + { + { + TransferableDataHelper aDataHelper( rEventObject.Contents ); + SwWrtShell& rSh = pView->GetWrtShell(); + + pView->m_nLastPasteDestination = SwTransferable::GetSotDestination( rSh ); + pView->m_bPasteState = aDataHelper.GetXTransferable().is() && + SwTransferable::IsPaste( rSh, aDataHelper ); + + pView->m_bPasteSpecialState = aDataHelper.GetXTransferable().is() && + SwTransferable::IsPasteSpecial( rSh, aDataHelper ); + } + + SfxBindings& rBind = pView->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_PASTE ); + rBind.Invalidate( SID_PASTE_SPECIAL ); + rBind.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS ); + } +} + +void SwClipboardChangeListener::AddRemoveListener( bool bAdd ) +{ + 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 000000000..f2d10b466 --- /dev/null +++ b/sw/source/uibase/uiview/view.cxx @@ -0,0 +1,1871 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::scanner; + +#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; + +SearchAttrItemList* SwView::s_pSearchList = nullptr; +SearchAttrItemList* SwView::s_pReplaceList = nullptr; + +SfxDispatcher &SwView::GetDispatcher() +{ + return *GetViewFrame()->GetDispatcher(); +} + +void SwView::ImpSetVerb( SelectionType nSelType ) +{ + bool bResetVerbs = m_bVerbsActive; + if ( !GetViewFrame()->GetFrame().IsInPlace() && + (SelectionType::Ole|SelectionType::Graphic) & nSelType ) + { + if ( m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE ) + { + 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( pTopShell ); + if ( pAsFormShell ) + { + pAsFormShell->ForgetActiveControl(); + const_cast< SwView* >( this )->AttrChangedNotify(nullptr); + } + else if ( m_pPostItMgr ) + { + SwAnnotationShell* pAsAnnotationShell = dynamic_cast( pTopShell ); + if ( pAsAnnotationShell ) + { + m_pPostItMgr->SetActiveSidebarWin(nullptr); + const_cast< SwView* >( this )->AttrChangedNotify(nullptr); + } + } + if( GetWrtShellPtr() ) + { + SwWrtShell& rWrtShell = GetWrtShell(); + rWrtShell.GetDoc()->getIDocumentLayoutAccess().SetCurrentViewShell( GetWrtShellPtr() ); + 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( 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 getLayoutManager(const SfxViewFrame& rViewFrame) +{ + uno::Reference xLayoutManager; + uno::Reference 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 + + if(m_bInDtor) + 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; + + 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 ); + } + 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()) + 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( 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(pFirst) - *static_cast(pSecond); + } +} + +IMPL_LINK_NOARG(SwView, AttrChangedNotify, LinkParamNone*, void) +{ + if ( GetEditWin().IsChainMode() ) + GetEditWin().SetChainMode( false ); + + //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 SfxPoolItem *pItem; + if ( SfxItemState::SET != GetObjectShell()->GetMedium()->GetItemSet()-> + GetItemState( SID_HIDDEN, false, &pItem ) || + !static_cast(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; + const SfxPoolItem *pItem; + // 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, pItem ); + eStateProtAll = rDis.QueryState( FN_EDIT_REGION, pItem ); + 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, SID_EMOJI_CONTROL, 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_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_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(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(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 *_pFrame, SfxViewShell* pOldSh ) + : SfxViewShell( _pFrame, SWVIEWFLAGS ), + m_nNewPage(USHRT_MAX), + m_nOldPageNum(0), + m_pNumRuleNodeFromDoc(nullptr), + m_pEditWin( VclPtr::Create( &_pFrame->GetWindow(), *this ) ), + m_pShell(nullptr), + m_pFormShell(nullptr), + m_pHScrollbar(nullptr), + m_pVScrollbar(nullptr), + m_pScrollFill(VclPtr::Create( &_pFrame->GetWindow(), WB_SIZEABLE )), + m_pVRuler(VclPtr::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_pFormatClipboard(new SwFormatClipboard()), + m_nSelectionType( SelectionType::All ), + m_nPageCnt(0), + m_nDrawSfxId( USHRT_MAX ), + m_nFormSfxId( USHRT_MAX ), + m_nLastPasteDestination( static_cast(0xFFFF) ), + m_nLeftBorderDistance( 0 ), + m_nRightBorderDistance( 0 ), + m_eLastSearchCommand( static_cast(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_nLOKPageUpDownOffset(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 , + // 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 . + + bDocSzUpdated = true; + + CreateScrollbar( true ); + CreateScrollbar( false ); + + m_pViewImpl.reset(new SwView_Impl(this)); + SetName("View"); + SetWindow( m_pEditWin ); + + m_aTimer.SetTimeout( 120 ); + + SwDocShell& rDocSh = dynamic_cast(*_pFrame->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(&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(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(pExistingSh) != nullptr) + bOldShellWasSrcView = true; + } + + SAL_INFO( "sw.ui", "before create WrtShell" ); + if (SwView *pView = dynamic_cast(pExistingSh)) + { + m_pWrtShell.reset(new SwWrtShell(*pView->m_pWrtShell, m_pEditWin, *this)); + } + else if (SwWrtShell *pWrtShell = dynamic_cast(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(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(pExistingSh)->ResetFormDesignMode() && + m_pWrtShell->HasDrawView() ) + { + SdrView* pDrawView = m_pWrtShell->GetDrawView(); + pDrawView->SetDesignMode( static_cast(pExistingSh)->FormDesignModeToReset() ); + } + } + } + SAL_INFO( "sw.ui", "after create WrtShell" ); + m_pHRuler = VclPtr::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* pViewFrame = GetViewFrame(); + + StartListening(*pViewFrame, 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 (!utl::ConfigManager::IsFuzzing() && 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(); + m_pHScrollbar->SetAuto(bBrowse); + if( aUsrPref.IsViewHRuler() ) + CreateTab(); + if( aUsrPref.IsViewVRuler() ) + CreateVRuler(); + + m_pWrtShell->SetUIOptions( aUsrPref ); + m_pWrtShell->SetReadOnlyAvailable( aUsrPref.IsCursorInProtectedArea() ); + m_pWrtShell->ApplyAccessibilityOptions(SW_MOD()->GetAccessibilityOptions()); + + if( m_pWrtShell->GetDoc()->getIDocumentState().IsUpdateExpField() ) + { + if (m_pWrtShell->GetDoc()->GetDocumentFieldsManager().containsUpdatableFields()) + { + SET_CURR_SHELL(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* pVFrame = 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 == pVFrame ) && + !bIsDocModified ) + { + m_pWrtShell->ResetModified(); + } + + g_bNoInterrupt = bOld; + + // If a new GlobalDoc will be created, the navigator will also be generated. + if( dynamic_cast(&rDocSh) != nullptr && + !pVFrame->GetChildWindow( SID_NAVIGATOR )) + { + SfxBoolItem aNavi(SID_NAVIGATOR, true); + GetDispatcher().ExecuteList(SID_NAVIGATOR, SfxCallMode::ASYNCHRON, { &aNavi }); + } + + uno::Reference< frame::XFrame > xFrame = pVFrame->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_aTimer.SetDebugName( "sw::SwView m_aTimer" ); + m_bAttrChgNotified = m_bAttrChgNotifiedWithRegistrations = false; + if (bOldModifyFlag) + rDocSh.EnableSetModified(); + InvalidateBorder(); + + if( !m_pHScrollbar->IsVisible( true ) ) + ShowHScrollbar( false ); + if( !m_pVScrollbar->IsVisible( true ) ) + ShowVScrollbar( false ); + + GetViewFrame()->GetWindow().AddChildEventListener( LINK( this, SwView, WindowChildEventListener ) ); +} + +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"); + SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", ""); + SfxLokHelper::notifyOtherViews(this, LOK_CALLBACK_GRAPHIC_VIEW_SELECTION, "selection", "EMPTY"); + + // 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 ? m_pWrtShell->GetDrawView() : nullptr; + if( pSdrView && pSdrView->IsTextEdit() ) + pSdrView->SdrEndTextEdit( true ); + + SetWindow( nullptr ); + + m_pViewImpl->Invalidate(); + EndListening(*GetViewFrame()); + EndListening(*GetDocShell()); + m_pScrollFill.disposeAndClear(); + m_pWrtShell.reset(); // reset here so that it is not accessible by the following dtors. + 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(); +} + +SwDocShell* SwView::GetDocShell() +{ + SfxObjectShell* pDocShell = GetViewFrame()->GetObjectShell(); + return dynamic_cast( 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(m_pWrtShell->GetViewOptions()->GetZoomType()));//eZoom; + rUserData += ";"; + rUserData += FrameTypeFlags::NONE == m_pWrtShell->GetSelFrameType() ? OUStringLiteral("0") : OUStringLiteral("1"); +} + +// Set CursorPos + +static bool lcl_IsOwnDocument( SwView& rView ) +{ + uno::Reference xDPS( + rView.GetDocShell()->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference xDocProps + = xDPS->getDocumentProperties(); + OUString Created = xDocProps->getAuthor(); + OUString Changed = xDocProps->getModifiedBy(); + OUString FullName = SW_MOD()->GetUserOptions().GetFullName(); + return (!FullName.isEmpty() && + (!Changed.isEmpty() && Changed == FullName )) || + (Changed.isEmpty() && !Created.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) ) + { + bool bIsOwnDocument = lcl_IsOwnDocument( *this ); + + SET_CURR_SHELL(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? + long nX = rUserData.getToken( 0, ';', nPos ).toInt32(), + nY = rUserData.getToken( 0, ';', nPos ).toInt32(); + Point aCursorPos( nX, nY ); + + sal_uInt16 nZoomFactor = + static_cast< sal_uInt16 >( rUserData.getToken(0, ';', nPos ).toInt32() ); + + long nLeft = rUserData.getToken(0, ';', nPos ).toInt32(), + nTop = rUserData.getToken(0, ';', nPos ).toInt32(), + nRight = rUserData.getToken(0, ';', nPos ).toInt32(), + nBottom= rUserData.getToken(0, ';', nPos ).toInt32(); + + const long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2; + if ( nBottom <= (m_pWrtShell->GetDocSize().Height()+nAdd) ) + { + 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(static_cast(rUserData.getToken(nOff, ';', nPos ).toInt32())); + else + { + eZoom = SvxZoomType::PERCENT; + ++nOff; + } + + bool bSelectObj = (0 != rUserData.getToken( nOff, ';', nPos ).toInt32()) + && 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 long nXTmp = m_sNewCursorPos.getToken( 0, ';', nIdx ).toInt32(); + const long nYTmp = m_sNewCursorPos.getToken( 0, ';', nIdx ).toInt32(); + 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 ); + if (!rSequence.hasElements()) + return; + + SET_CURR_SHELL(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_Int64 nRight = nLeft; + sal_Int64 nBottom = LONG_MIN; + 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, bGotVisibleRight = false, + bGotVisibleBottom = false, bGotZoomType = false, + bGotZoomFactor = false, bGotIsSelectedFrame = false, + bGotViewLayoutColumns = false, bGotViewLayoutBookMode = false, + bBrowseMode = false, bGotBrowseMode = false; + + for (const beans::PropertyValue& rValue : rSequence) + { + if ( rValue.Name == "ViewLeft" ) + { + rValue.Value >>= nX; + nX = convertMm100ToTwip( nX ); + } + else if ( rValue.Name == "ViewTop" ) + { + rValue.Value >>= nY; + nY = convertMm100ToTwip( nY ); + } + else if ( rValue.Name == "VisibleLeft" ) + { + rValue.Value >>= nLeft; + nLeft = convertMm100ToTwip( nLeft ); + bGotVisibleLeft = true; + } + else if ( rValue.Name == "VisibleTop" ) + { + rValue.Value >>= nTop; + nTop = convertMm100ToTwip( nTop ); + bGotVisibleTop = true; + } + else if ( rValue.Name == "VisibleRight" ) + { + rValue.Value >>= nRight; + nRight = convertMm100ToTwip( nRight ); + bGotVisibleRight = true; + } + else if ( rValue.Name == "VisibleBottom" ) + { + rValue.Value >>= nBottom; + nBottom = convertMm100ToTwip( nBottom ); + bGotVisibleBottom = 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(rValue.Value); + bGotViewLayoutBookMode = true; + } + else if ( rValue.Name == "IsSelectedFrame" ) + { + rValue.Value >>= bSelectedFrame; + bGotIsSelectedFrame = true; + } + else if (rValue.Name == "ShowOnlineLayout") + { + rValue.Value >>= bBrowseMode; + bGotBrowseMode = 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)); + } + if (bGotVisibleBottom) + { + Point aCursorPos( nX, nY ); + const long nAdd = m_pWrtShell->GetViewOptions()->getBrowseMode() ? DOCUMENTBORDER : DOCUMENTBORDER*2; + if (nBottom <= (m_pWrtShell->GetDocSize().Height()+nAdd) ) + { + m_pWrtShell->EnableSmooth( false ); + const tools::Rectangle aVis( nLeft, nTop, nRight, nBottom ); + + 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 ); + } + SelectShell(); + + // 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(aVis.TopLeft()); + // make sure the document is still centered + const SwTwips lBorder = IsDocumentBorder() ? DOCUMENTBORDER : 2 * DOCUMENTBORDER; + SwTwips nEditWidth = GetEditWin().GetOutputSize().Width(); + if(nEditWidth > (m_aDocSz.Width() + lBorder )) + aTopLeft.setX( ( m_aDocSz.Width() + lBorder - nEditWidth ) / 2 ); + else + { + //check if the values are possible + long nXMax = m_pHScrollbar->GetRangeMax() - m_pHScrollbar->GetVisibleSize(); + if( aTopLeft.X() > nXMax ) + aTopLeft.setX( nXMax < 0 ? 0 : nXMax ); + } + SetVisArea( aTopLeft ); + } + else if (bGotVisibleLeft && bGotVisibleTop && bGotVisibleRight && bGotVisibleBottom ) + SetVisArea( aVis ); + } + + 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 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)); + + 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())); + + 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( long 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 ) +{ + 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(dynamic_cast(&rHint)) + { + bool bDesignMode = static_cast(rHint).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 . + 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(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 ) + { + Graphic aGrf(aScanBmp); + m_pWrtShell->Insert( 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* pVFrame = GetViewFrame(); + pVFrame->SetChildWindow( SwInputChild::GetChildWindowId(), false ); + if( pVFrame->GetDispatcher()->IsLocked() ) + pVFrame->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(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(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); +} + +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 000000000..d15c0bcc1 --- /dev/null +++ b/sw/source/uibase/uiview/view0.cxx @@ -0,0 +1,648 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ShellClass_SwView +#define ShellClass_Text +#define ShellClass_TextDrawText + +#include +#include +#include + +using namespace ::com::sun::star; + +#include +#include + +#include +#include + +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(SvtAccessibilityOptions const & rAccessibilityOptions) +{ + m_pWrtShell->ApplyAccessibilityOptions(rAccessibilityOptions); + //to enable the right state of the selection cursor in readonly documents + if(GetDocShell()->IsReadOnly()) + m_pWrtShell->ShowCursor(); + +} + +void SwView::SetMailMergeConfigItem(std::shared_ptr const & rConfigItem) +{ + m_pViewImpl->SetMailMergeConfigItem(rConfigItem); + UIFeatureChanged(); +} + +std::shared_ptr const & SwView::GetMailMergeConfigItem() const +{ + return m_pViewImpl->GetMailMergeConfigItem(); +} + +static bool lcl_IsViewMarks( const SwViewOption& rVOpt ) +{ + return rVOpt.IsHardBlank() && + rVOpt.IsSoftHyph() && + SwViewOption::IsFieldShadings(); +} +static void lcl_SetViewMarks(SwViewOption& rVOpt, bool bOn ) +{ + rVOpt.SetHardBlank(bOn); + rVOpt.SetSoftHyph(bOn); + SwViewOption::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_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 ) + { + 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( SwViewOption::IsDocBoundaries()); break; + case FN_VIEW_GRAPHIC: + aBool.SetValue( pOpt->IsGraphic() ); break; + case FN_VIEW_FIELDS: + aBool.SetValue( SwViewOption::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( SwViewOption::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 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; + } + + if( nWhich ) + { + aBool.SetWhich( nWhich ); + rSet.Put( aBool ); + } + nWhich = aIter.NextWhich(); + } +} + +// execute view options + +void SwView::ExecViewOptions(SfxRequest &rReq) +{ + std::unique_ptr pOpt(new SwViewOption( *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(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 = !SwViewOption::IsFieldShadings() ; + SwViewOption::SetAppearanceFlag(ViewOptFlags::FieldShadings, bFlag, true ); + break; + + case FN_VIEW_BOUNDS: + if( STATE_TOGGLE == eState ) + bFlag = !SwViewOption::IsDocBoundaries(); + SwViewOption::SetAppearanceFlag(ViewOptFlags::DocBoundaries, 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 = !SwViewOption::IsTableBoundaries(); + SwViewOption::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_VIEW_META_CHARS: + if( STATE_TOGGLE == eState ) + bFlag = !pOpt->IsViewMetaChars(); + + lcl_SetViewMetaChars( *pOpt, bFlag ); + break; + + case SID_AUTOSPELL_CHECK: + if( STATE_TOGGLE == eState ) + { + bFlag = !pOpt->IsOnlineSpell(); + bSet = bFlag; + } + + pOpt->SetOnlineSpell(bSet); + { + SvtLinguConfig aCfg; + aCfg.SetProperty( UPN_IS_SPELL_AUTO, uno::makeAny( 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 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; + + default: + OSL_FAIL("wrong request method"); + return; + } + + // Set UserPrefs, mark request as modified + bool bWebView = dynamic_cast(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 pDlg(pFact->CreateSwFootNoteOptionDlg(GetFrameWeld(), GetWrtShell())); + pDlg->Execute(); +} + +void SwView::ExecNumberingOutline(SfxItemPool & rPool) +{ + SfxItemSet aTmp(rPool, svl::Items{}); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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 000000000..1484b3005 --- /dev/null +++ b/sw/source/uibase/uiview/view1.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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* pVFrame = GetViewFrame(); + SwFieldDlgWrapper *pWrp = static_cast(pVFrame->GetChildWindow(nId)); + if (pWrp) + pWrp->ReInitDlg(GetDocShell()); + + // Initialize RedlineDlg newly if necessary + nId = SwRedlineAcceptChild::GetChildWindowId(); + SwRedlineAcceptChild *pRed = static_cast(pVFrame->GetChildWindow(nId)); + if (pRed) + pRed->ReInitDlg(GetDocShell()); + + // reinit IdxMarkDlg + nId = SwInsertIdxMarkWrapper::GetChildWindowId(); + SwInsertIdxMarkWrapper *pIdxMrk = static_cast(pVFrame->GetChildWindow(nId)); + if (pIdxMrk) + pIdxMrk->ReInitDlg(*m_pWrtShell); + + // reinit AuthMarkDlg + nId = SwInsertAuthMarkWrapper::GetChildWindowId(); + SwInsertAuthMarkWrapper *pAuthMrk = static_cast(pVFrame-> + 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) +{ + if( g_bFlushCharBuffer ) // Are Characters still in the input buffer? + GetEditWin().FlushInBuffer(); + + 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* pVFrame = GetViewFrame(); + if (pVFrame != nullptr) + { + pVFrame->ToggleChildWindow(FN_WORDCOUNT_DIALOG); + pShell->Invalidate(nSlot); + + SwWordCountWrapper *pWrdCnt = static_cast(pVFrame->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 000000000..6245bf7f4 --- /dev/null +++ b/sw/source/uibase/uiview/view2.cxx @@ -0,0 +1,2573 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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; + +static void lcl_SetAllTextToDefaultLanguage( SwWrtShell &rWrtSh, sal_uInt16 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 + std::set aAttribs; + aAttribs.insert( nWhichId ); + rWrtSh.ResetAttr( aAttribs ); + + 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() && 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 sal_uInt16 aRotation = aMetadata.getRotation(); + if (aRotation != 0) + { + 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.Insert( sURL, rFilter, aGraphic, &aFrameManager ); + } + else + { + rShell.Insert( 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 pFileDlg(new FileDialogHelper( + ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE, + FileDialogFlags::Graphic, GetFrameWeld())); + pFileDlg->SetTitle(SwResId(STR_INSERT_GRAPHIC )); + pFileDlg->SetContext( FileDialogHelper::SW_INSERT_GRAPHIC ); + + uno::Reference < XFilePicker3 > xFP = pFileDlg->GetFilePicker(); + uno::Reference < XFilePickerControlAccess > xCtrlAcc(xFP, UNO_QUERY); + if(nHtmlMode & HTMLMODE_ON) + { + xCtrlAcc->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, makeAny(true)); + xCtrlAcc->enableControl( ExtendedFilePickerElementIds::CHECKBOX_LINK, false); + } + + std::vector 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& 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 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::get()); + + xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE, + ListboxControlActions::ADD_ITEMS , aTemplates ); + + Any aSelectPos(&nSelect, cppu::UnoType::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(SID_INSERT_GRAPHIC); + bool bShowError = !pName; + if( pName +#if HAVE_FEATURE_DESKTOP + || ERRCODE_NONE == pFileDlg->Execute() +#endif + ) + { + + OUString aFileName, aFilterName; + if ( pName ) + { + aFileName = pName->GetValue(); + const SfxStringItem* pFilter = rReq.GetArg(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(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(FN_PARAM_1); + const SfxStringItem* pStyle = rReq.GetArg(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(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 && SvtMiscOptions().ShowLinkWarningDialog() ) + { + SvxLinkWarningDialog aWarnDlg(GetFrameWeld(), pFileDlg->GetPath()); + if (aWarnDlg.run() != RET_OK) + bAsLink=false; // don't store as link + } + } +#endif + + SwWrtShell& rSh = GetWrtShell(); + rSh.LockPaint(); + 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 ); + } + + const char* pResId(nullptr); + 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 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 pDlg(pFact->CreateVclSwViewDialog(*this)); + pDlg->Execute(); + break; + } + case FN_EDIT_LINK_DLG: + EditLinkDlg(); + break; + case FN_REFRESH_VIEW: + GetEditWin().Invalidate(); + 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 FN_REDLINE_ON: + { + if( pArgs && + SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem )) + { + IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); + Sequence aPasswd = rIDRA.GetRedlinePassword(); + if( aPasswd.hasElements() ) + { + OSL_ENSURE( !static_cast(pItem)->GetValue(), "SwView::Execute(): password set and redlining off doesn't match!" ); + + // dummy password from OOXML import: only confirmation dialog + if (aPasswd.getLength() == 1 && aPasswd[0] == 1) + { + std::unique_ptr xWarn(Application::CreateMessageDialog(m_pWrtShell->GetView().GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::YesNo, + SfxResId(RID_SVXSTR_END_REDLINING_WARNING))); + xWarn->set_default_response(RET_NO); + if (xWarn->run() == RET_YES) + rIDRA.SetRedlinePassword(Sequence ()); + else + break; + } + else + { + // 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()); + Sequence aNewPasswd = rIDRA.GetRedlinePassword(); + SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd ); + if(SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd)) + rIDRA.SetRedlinePassword(Sequence ()); + else + { // xmlsec05: message box for wrong password + break; + } + } + } + + const RedlineFlags nOn = static_cast(pItem)->GetValue() + ? RedlineFlags::On : RedlineFlags::NONE; + const RedlineFlags nMode = m_pWrtShell->GetRedlineFlags(); + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn); + + // Notify all view shells of this document, as the track changes mode is document-global. + SwDocShell* pDocShell = GetDocShell(); + 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 aPasswd = rIDRA.GetRedlinePassword(); + if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem ) + && static_cast(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 aNewPasswd = + rIDRA.GetRedlinePassword(); + SvPasswordHelper::GetHashPassword( aNewPasswd, sNewPasswd ); + if(!aPasswd.hasElements()) + { + rIDRA.SetRedlinePassword(aNewPasswd); + } + else if(SvPasswordHelper::CompareHashPassword(aPasswd, sNewPasswd)) + { + rIDRA.SetRedlinePassword(Sequence ()); + 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 + m_pWrtShell->StartAllAction(); + m_pWrtShell->GetLayout()->SetHideRedlines( + !static_cast(pItem)->GetValue()); + 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(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) + { + if (FN_REDLINE_ACCEPT_DIRECT == nSlot || FN_REDLINE_ACCEPT_TONEXT == nSlot) + m_pWrtShell->AcceptRedlinesInSelection(); + else + m_pWrtShell->RejectRedlinesInSelection(); + } + 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); + + assert(pRedline != nullptr); + if (pRedline) + { + 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(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()) + { + OString aPayload(".uno:CurrentTrackedChangeId="); + sal_uInt32 nRedlineId = pNext->GetId(); + aPayload += OString::number(nRedlineId); + libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload.getStr()); + } + + m_pWrtShell->SetInSelect(); + } + + } + break; + + case FN_REDLINE_PREV_CHANGE: + { + const SwRangeRedline *pPrev = m_pWrtShell->SelPrevRedline(); + + if (pPrev) + { + if (comphelper::LibreOfficeKit::isActive()) + { + OString aPayload(".uno:CurrentTrackedChangeId="); + sal_uInt32 nRedlineId = pPrev->GetId(); + aPayload += OString::number(nRedlineId); + libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload.getStr()); + } + + 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( SfxItemState::SET == pArgs->GetItemState( SID_FILE_NAME, false, &pItem )) + sFileName = static_cast(pItem)->GetValue(); + bHasFileName = !sFileName.isEmpty(); + + if( SfxItemState::SET == pArgs->GetItemState( SID_FILTER_NAME, false, &pItem )) + sFilterName = static_cast(pItem)->GetValue(); + + if( SfxItemState::SET == pArgs->GetItemState( SID_VERSION, false, &pItem )) + { + nVersion = static_cast(pItem)->GetValue(); + m_pViewImpl->SetParam( nVersion ); + } + if( SfxItemState::SET == pArgs->GetItemState( SID_NO_ACCEPT_DIALOG, false, &pItem )) + { + bNoAcceptDialog = static_cast(pItem)->GetValue(); + } + } + + m_pViewImpl->InitRequest( rReq ); + long nFound = InsertDoc( nSlot, sFileName, sFilterName, nVersion ); + + if ( bHasFileName ) + { + rReq.SetReturnValue( SfxInt32Item( nSlot, nFound )); + + if (nFound > 0 && !bNoAcceptDialog) // show Redline browser + { + SfxViewFrame* pVFrame = GetViewFrame(); + pVFrame->ShowChildWindow(FN_REDLINE_ACCEPT); + + // re-initialize the Redline dialog + const sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId(); + SwRedlineAcceptChild *pRed = static_cast( + pVFrame->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(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(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()->GetWindow().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 ) + { + 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: + { + if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_DEFTABSTOP, false, &pItem)) + { + SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP ); + const sal_uInt16 nTab = static_cast(pItem)->GetValue(); + MakeDefTabs( nTab, aDefTabs ); + m_pWrtShell->SetDefault( aDefTabs ); + } + } + break; + case SID_ATTR_LANGUAGE : + if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_LANGUAGE, false, &pItem)) + { + SvxLanguageItem aLang(static_cast(pItem)->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_NAV_ELEMENT: + { + // nothing here on purpose - if removed only the listbox that changed is changed + } + break; + case FN_SCROLL_PREV: + case FN_SCROLL_NEXT: + { + bool *pbNext = new bool(true); // FN_SCROLL_NEXT + if (nSlot == FN_SCROLL_PREV) + *pbNext = false; + // #i75416# move the execution of the search to an asynchronously called static link + Application::PostUserEvent( LINK(this, SwView, MoveNavigationHdl), pbNext ); + } + break; + case SID_JUMPTOMARK: + if( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_JUMPTOMARK, false, &pItem)) + JumpToSwMark( static_cast(pItem)->GetValue() ); + break; + case SID_GALLERY : + // First make sure that the sidebar is visible + GetViewFrame()->ShowChildWindow(SID_SIDEBAR); + + ::sfx2::sidebar::Sidebar::ShowPanel( + "GalleryPanel", + GetViewFrame()->GetFrame().GetFrameInterface()); + break; + case SID_AVMEDIA_PLAYER : + GetViewFrame()->ChildWindowExecute(rReq); + break; + case SID_VIEW_DATA_SOURCE_BROWSER: + { + SfxViewFrame* pVFrame = GetViewFrame(); + pVFrame->ChildWindowExecute(rReq); + if(pVFrame->HasChildWindow(SID_BROWSER)) + { + const SwDBData& rData = GetWrtShell().GetDBDesc(); + 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(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 + 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 aProperties(3); + PropertyValue* pValues = aProperties.getArray(); + pValues[0].Name = "DataSourceName"; + pValues[1].Name = "Command"; + pValues[2].Name = "CommandType"; + pValues[0].Value <<= aData.sDataSource; + pValues[1].Value <<= aData.sCommand; + pValues[2].Value <<= 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* pTmpFrame = GetViewFrame(); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateMailMergeCreateFromDlg(pTmpFrame->GetWindow().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* pViewFrame = GetViewFrame(); + if (rReq.GetArgs() != nullptr) + pViewFrame->SetChildWindow (FN_SPELL_GRAMMAR_DIALOG, + static_cast( (rReq.GetArgs()-> + Get(FN_SPELL_GRAMMAR_DIALOG))).GetValue()); + else + pViewFrame->ToggleChildWindow(FN_SPELL_GRAMMAR_DIALOG); + + pViewFrame->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; + + 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(sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, const OUString& rPgStr) +{ + OUString sTemp(GetPageStr( nPhyNum, nVirtNum, rPgStr )); + const SfxStringItem aTmp( FN_STAT_PAGE, sTemp ); + // Used to distinguish which tooltip to show + const SfxBoolItem bExtendedTooltip( FN_STAT_PAGE, + !rPgStr.isEmpty() && OUString::number(nPhyNum) != rPgStr + && nPhyNum != nVirtNum ); + + SfxBindings &rBnd = GetViewFrame()->GetBindings(); + rBnd.SetState( aTmp ); + rBnd.Update( FN_STAT_PAGE ); + rBnd.SetState( bExtendedTooltip ); + rBnd.Update( 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: { + // number of pages, log. page number + sal_uInt16 nPage, nLogPage; + OUString sDisplay; + rShell.GetPageNumber( -1, rShell.IsCursorVisible(), nPage, nLogPage, sDisplay ); + OUString sTemp( GetPageStr( nPage, nLogPage, sDisplay ) ); + const SfxStringItem aTmp( FN_STAT_PAGE, sTemp ); + GetViewFrame()->GetBindings().SetState( aTmp ); + // Used to distinguish which tooltip to show + const SfxBoolItem bExtendedTooltip( FN_STAT_PAGE, !sDisplay.isEmpty() && + OUString::number( nPage ) != sDisplay && + nPage != nLogPage ); + GetViewFrame()->GetBindings().SetState( bExtendedTooltip ); + //if existing page number is not equal to old page number, send out this event. + if (m_nOldPageNum != nLogPage ) + { + if (m_nOldPageNum != 0) + SwCursorShell::FirePageChangeEvent(m_nOldPageNum, nLogPage); + m_nOldPageNum = nLogPage; + } + 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; + const char* pResId = selectionStats.nWord ? STR_WORDCOUNT : STR_WORDCOUNT_NO_SELECTION; + const char* pWordResId = selectionStats.nWord ? STR_WORDCOUNT_WORDARG : STR_WORDCOUNT_WORDARG_NO_SELECTION; + const char* 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 ) ); + + SwWordCountWrapper *pWrdCnt = static_cast(GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); + if (pWrdCnt) + pWrdCnt->SetCounts(selectionStats, documentStats); + } + 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 long nOf = pVOpt->GetDocumentBorder() * 2; + long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width(); + nTmpWidth += nOf; + aPageSize.AdjustHeight(nOf ); + long nFac = aWindowSize.Width() * 100 / nTmpWidth; + + 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 + { + OUString sStr; + if( rShell.IsCursorInTable() ) + { + // table name + cell coordinate + sStr = rShell.GetTableFormat()->GetName() + ":"; + sStr += rShell.GetBoxNms(); + } + 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(); + else + { + OSL_ENSURE( false, + "Unknown kind of section" ); + sStr = pCurrSect->GetSectionName(); + } + } + break; + default: + sStr = pCurrSect->GetSectionName(); + 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()) + { + SfxItemSet aSet(GetPool(), + svl::Items{}); + 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; + sStr += rNumStyle; + } + } + } + if (!sStr.isEmpty()) + sStr += sStatusDelim; + sStr += SwResId(STR_NUM_LEVEL) + OUString::number( nNumLevel + 1 ); + + } + } + 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( rShell.HasReadonlySel() ) + { + if (!sStr.isEmpty()) + sStr = sStatusDelim + sStr; + sStr = SwResId(SW_STR_READONLY) + sStr; + } + if (!sStr.isEmpty()) + rSet.Put( SfxStringItem( SID_TABLE_CELL, sStr )); + } + 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_BOOKMARK: + if ( pArgs ) + { + if (SfxItemState::SET == pArgs->GetItemState( nWhich, true, &pItem)) + { + const IDocumentMarkAccess* pMarkAccess = rSh.getIDocumentMarkAccess(); + const sal_Int32 nIdx = static_cast(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: + { + GetViewFrame()->GetDispatcher()->Execute(FN_FORMAT_PAGE_DLG, + SfxCallMode::SYNCHRON|SfxCallMode::RECORD ); + } + break; + case SID_ATTR_ZOOM: + { + if ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) + { + const SfxItemSet *pSet = nullptr; + ScopedVclPtr pDlg; + if ( pArgs ) + pSet = pArgs; + else + { + const SwViewOption& rViewOptions = *rSh.GetViewOptions(); + SfxItemSet aCoreSet(m_pShell->GetPool(), svl::Items{} ); + 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()->GetWindow().GetFrameWeld(), aCoreSet)); + pDlg->SetLimits( MINZOOM, MAXZOOM ); + if( pDlg->Execute() != RET_CANCEL ) + pSet = pDlg->GetOutputItemSet(); + } + + const SfxPoolItem* pViewLayoutItem = nullptr; + if ( pSet && SfxItemState::SET == pSet->GetItemState(SID_ATTR_VIEWLAYOUT, true, &pViewLayoutItem)) + { + const sal_uInt16 nColumns = static_cast(pViewLayoutItem)->GetValue(); + const bool bBookMode = static_cast(pViewLayoutItem)->IsBookMode(); + SetViewLayout( nColumns, bBookMode ); + } + + if ( pSet && SfxItemState::SET == pSet->GetItemState(SID_ATTR_ZOOM, true, &pItem)) + { + SvxZoomType eType = static_cast(pItem)->GetType(); + SetZoom( eType, static_cast(pItem)->GetValue() ); + } + bUp = true; + if ( pItem ) + rReq.AppendItem( *pItem ); + rReq.Done(); + } + } + break; + + case SID_ATTR_VIEWLAYOUT: + { + if ( pArgs && !rSh.getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) && + ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) ) + { + if ( SfxItemState::SET == pArgs->GetItemState(SID_ATTR_VIEWLAYOUT, true, &pItem )) + { + const sal_uInt16 nColumns = static_cast(pItem)->GetValue(); + const bool bBookMode = !(0 == nColumns || 0 != (nColumns % 2)) && + static_cast(pItem)->IsBookMode(); + + SetViewLayout( nColumns, bBookMode ); + } + + bUp = true; + rReq.Done(); + + InvalidateRulerPos(); + } + } + break; + + case SID_ATTR_ZOOMSLIDER: + { + if ( pArgs && ( ( GetDocShell()->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) || !GetDocShell()->IsInPlaceActive() ) ) + { + if ( SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOMSLIDER, true, &pItem )) + { + const sal_uInt16 nCurrentZoom = static_cast(pItem)->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(pItem)->GetValue() ) + { + case 0: rSh.EnterStdMode(); break; + case 1: rSh.EnterExtMode(); break; + case 2: rSh.EnterAddMode(); break; + case 3: rSh.EnterBlockMode(); break; + } + } + } + else + { + + if( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() ) + rSh.ToggleExtMode(); + else if ( rSh.IsExtMode() ) + { + rSh.ToggleExtMode(); + rSh.ToggleAddMode(); + } + else if ( rSh.IsAddMode() ) + { + rSh.ToggleAddMode(); + rSh.ToggleBlockMode(); + } + else + rSh.ToggleBlockMode(); + } + 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() +{ + bool bWeb = dynamic_cast( this ) != nullptr; + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateLinksDialog(GetViewFrame()->GetWindow().GetFrameWeld(), &GetWrtShell().GetLinkManager(), bWeb)); + pDlg->Execute(); +} + +bool SwView::JumpToSwMark( const OUString& rMark ) +{ + bool bRet = false; + if( !rMark.isEmpty() ) + { + // 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 == "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 = sName.copy( nNoPos + 1 ).toInt32(); + sName = sName.copy( 0, nNoPos ); + bRet = m_pWrtShell->GotoRefMark(sName, REF_SEQUENCEFLD, nSeqNo); + } + } + else if( sCmp == "text" ) + { + // normal text search + m_pWrtShell->EnterStdMode(); + + i18nutil::SearchOptions2 aSearchOpt( + SearchAlgorithms_ABSOLUTE, 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( !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 SfxPoolItem* pItem; + if( ( SfxItemState::SET == rMaster.GetAttrSet().GetItemState( RES_HEADER, false, &pItem ) && + static_cast(pItem)->IsActive() ) || + ( SfxItemState::SET == rMaster.GetAttrSet().GetItemState( RES_FOOTER, false, &pItem ) && + static_cast(pItem)->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( pItem )->GetValue(); + if ( SfxItemState::SET == rRequest.GetArgs()->GetItemState( FN_PARAM_1, true, &pItem ) ) + sFilter = static_cast(pItem )->GetValue(); + + bool bHasFileName = !sFile.isEmpty(); + long nFound = InsertDoc( nSlot, sFile, sFilter ); + + if ( bHasFileName ) + { + rRequest.SetReturnValue( SfxBoolItem( nSlot, nFound != -1 ) ); + rRequest.Done(); + } + } +} + +long SwView::InsertDoc( sal_uInt16 nSlotId, const OUString& rFileName, const OUString& rFilterName, sal_Int16 nVersion ) +{ + std::unique_ptr pMed; + SwDocShell* pDocSh = GetDocShell(); + + if( !rFileName.isEmpty() ) + { + SfxObjectFactory& rFact = pDocSh->GetFactory(); + std::shared_ptr 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 ); +} + +long SwView::InsertMedium( sal_uInt16 nSlotId, std::unique_ptr pMedium, sal_Int16 nVersion ) +{ + bool bInsert = false, bCompare = false; + 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 ); + ErrCode 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()); + uno::Reference 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( xDocSh.get() )->GetDoc() ); + else + nFound = m_pWrtShell->MergeDoc( *static_cast( xDocSh.get() )->GetDoc() ); + + m_pWrtShell->EndAllAction(); + + if (!bCompare && !nFound) + { + std::unique_ptr 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 + +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 + (void) bUseCurrentDocument; +#else + if(bUseCurrentDocument) + { + if(!GetWrtShell().IsAnyDatabaseFieldInDoc()) + { + //check availability of data sources (except biblio source) + uno::Reference xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference xDBContext = DatabaseContext::create(xContext); + bool bCallAddressPilot = false; + if ( lcl_NeedAdditionalDataSource( xDBContext ) ) + { + // no data sources are available - create a new one + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/datasourcesunavailabledialog.ui")); + std::unique_ptr 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 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* pVFrame = GetViewFrame(); + //at first hide the default field dialog if currently visible + pVFrame->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); + pVFrame->GetDispatcher()->ExecuteList(FN_INSERT_FIELD_DATA_ONLY, + SfxCallMode::SYNCHRON, { &aOn }); + return; + } + else + { + OUString sSource; + if(!GetWrtShell().IsFieldDataSourceAvailable(sSource)) + { + std::unique_ptr xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/warndatasourcedialog.ui")); + std::unique_ptr 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 pDlg(pFact->CreateVclDialog( nullptr, SID_OPTIONS_DATABASES )); + pDlg->Execute(); + } + return ; + } + } + SwDBManager* pDBManager = GetWrtShell().GetDBManager(); + + SwDBData aData; + SwWrtShell &rSh = GetWrtShell(); + + std::vector aDBNameList; + std::vector 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 = sDBName.getToken(0, DB_DELIM, nIdx).toInt32(); + } + rSh.EnterStdMode(); // force change in text shell; necessary for mixing DB fields + AttrChangedNotify(nullptr); + + if (pDBManager) + { + Sequence aProperties(3); + PropertyValue* pValues = aProperties.getArray(); + pValues[0].Name = "DataSourceName"; + pValues[1].Name = "Command"; + pValues[2].Name = "CommandType"; + pValues[0].Value <<= aData.sDataSource; + pValues[1].Value <<= aData.sCommand; + pValues[2].Value <<= aData.nCommandType; + pDBManager->ExecuteFormLetter(GetWrtShell(), aProperties); + } + } + else + { + // call documents and template dialog + SfxApplication* pSfxApp = SfxGetpApp(); + vcl::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->ToTop(); + } +#endif +} + +IMPL_LINK( SwView, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void ) +{ + if ( ERRCODE_NONE != _pFileDlg->GetError() ) + return; + + std::unique_ptr pMed = m_pViewImpl->CreateMedium(); + if ( !pMed ) + return; + + const sal_uInt16 nSlot = m_pViewImpl->GetRequest()->GetSlot(); + 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* pVFrame = GetViewFrame(); + pVFrame->ShowChildWindow(FN_REDLINE_ACCEPT); + + // re-initialize Redline dialog + sal_uInt16 nId = SwRedlineAcceptChild::GetChildWindowId(); + SwRedlineAcceptChild* pRed = static_cast(pVFrame->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 000000000..94ad59d1d --- /dev/null +++ b/sw/source/uibase/uiview/viewcoll.cxx @@ -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 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +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(pItem)->GetValue() != + GetWrtShell().GetCurPageStyle() ) + { + SfxStringItem aName(SID_STYLE_APPLY, + static_cast(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 000000000..c6f81808e --- /dev/null +++ b/sw/source/uibase/uiview/viewdlg.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 + +#include +#include +#include + +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(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 000000000..0283752c9 --- /dev/null +++ b/sw/source/uibase/uiview/viewdlg2.cxx @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +using namespace css; + +void SwView::ExecDlgExt(SfxRequest const &rReq) +{ + switch ( rReq.GetSlot() ) + { + case FN_INSERT_CAPTION: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDialog(pFact->CreateSwCaptionDialog(GetFrameWeld(), *this )); + pDialog->Execute(); + break; + } + case SID_INSERT_SIGNATURELINE: + case SID_EDIT_SIGNATURELINE: + { + VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); + const uno::Reference xModel(GetCurrentDocument()); + ScopedVclPtr 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 xModel(GetCurrentDocument()); + ScopedVclPtr pDialog(pFact->CreateQrCodeGenDialog( + GetFrameWeld(), xModel, rReq.GetSlot() == SID_EDIT_QRCODE)); + pDialog->Execute(); + break; + } + case SID_SIGN_SIGNATURELINE: + { + VclAbstractDialogFactory* pFact = VclAbstractDialogFactory::Create(); + const uno::Reference xModel(GetCurrentDocument()); + ScopedVclPtr pDialog( + pFact->CreateSignSignatureLineDialog(GetFrameWeld(), xModel)); + pDialog->Execute(); + break; + } + case FN_EDIT_FOOTNOTE: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr 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(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(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(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( this ) != nullptr; + if (pModOpt->IsInsWithCaption(bWeb)) + { + const InsCaptionOpt *pOpt = pModOpt->GetCapOption(bWeb, static_cast(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(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(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(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 000000000..281e2d095 --- /dev/null +++ b/sw/source/uibase/uiview/viewdraw.cxx @@ -0,0 +1,749 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +// Execute Drawing-Ids + +void SwView::ExecDraw(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); + + if (nSlotId == SID_OBJECT_SELECT && m_nFormSfxId == nSlotId) + { + bDeselect = true; + } + else if (nSlotId == SID_FM_CREATE_CONTROL) + { + const SfxUInt16Item* pIdentifierItem = rReq.GetArg(SID_FM_CONTROL_IDENTIFIER); + if( pIdentifierItem ) + { + sal_uInt16 nNewId = pIdentifierItem->GetValue(); + if (nNewId == m_nFormSfxId) + { + bDeselect = true; + GetViewFrame()->GetDispatcher()->Execute(SID_FM_LEAVE_CREATE); // Button should popping out + } + } + } + else if (nSlotId == SID_FM_CREATE_FIELDCONTROL) + { + FmFormView* pFormView = dynamic_cast(pSdrView); + if (pFormView) + { + const SfxUnoAnyItem* pDescriptorItem = rReq.GetArg(SID_FM_DATACCESS_DESCRIPTOR); + OSL_ENSURE( pDescriptorItem, "SwView::ExecDraw(SID_FM_CREATE_FIELDCONTROL): invalid request args!" ); + if( pDescriptorItem ) + { + svx::ODataAccessDescriptor aDescriptor( pDescriptorItem->GetValue() ); + SdrObjectUniquePtr 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(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.release()), 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) + { + SdrObject* pObj = nullptr; + svx::FontWorkGalleryDialog aDlg(rWin.GetFrameWeld(), *pSdrView); + aDlg.SetSdrObjectRef( &pObj, pSdrView->GetModel() ); + aDlg.run(); + if ( pObj ) + { + Size aDocSize( m_pWrtShell->GetDocSize() ); + const SwRect& rVisArea = m_pWrtShell->VisArea(); + Point aPos( rVisArea.Center() ); + Size aSize; + Size aPrefSize( pObj->GetSnapRect().GetSize() ); + + if( rVisArea.Width() > aDocSize.Width()) + aPos.setX( aDocSize.Width() / 2 + rVisArea.Left() ); + + if(rVisArea.Height() > aDocSize.Height()) + aPos.setY( aDocSize.Height() / 2 + rVisArea.Top() ); + + if( aPrefSize.Width() && aPrefSize.Height() ) + aSize = rWin.PixelToLogic(aPrefSize, MapMode(MapUnit::MapTwip)); + else + aSize = Size( 2835, 2835 ); + + m_pWrtShell->EnterStdMode(); + m_pWrtShell->SwFEShell::InsertDrawObj( *pObj, aPos ); + rReq.Ignore (); + } + } + 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(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 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) ); + 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: + { + const SfxUInt16Item* pIdentifierItem = rReq.GetArg(SID_FM_CONTROL_IDENTIFIER); + if( pIdentifierItem ) + nSlotId = pIdentifierItem->GetValue(); + pFuncPtr.reset( new ConstFormControl(m_pWrtShell.get(), m_pEditWin, this) ); + m_nFormSfxId = nSlotId; + } + 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(SID_OBJECT_SELECT == m_nDrawSfxId ) + { + m_pWrtShell->GotoObj(true); + } + else if (dynamic_cast(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) + { + // 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) + { + 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(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. + ( dynamic_cast< const SdrTextObj *>( pObj ) != nullptr || + ( dynamic_cast< const SwDrawVirtObj *>( pObj ) != nullptr && + dynamic_cast< const SdrTextObj *>(&static_cast(pObj)->GetReferencedObj() ) != nullptr ) ) && + + m_pWrtShell->IsSelObjProtected(FlyProtectFlags::Content) == FlyProtectFlags::NONE) + { + // 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 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 xHyphenator( ::GetHyphenator() ); + pOutliner->SetHyphenator( xHyphenator ); + pSh->SetCalcFieldValueHdl(pOutliner.get()); + + EEControlBits nCntrl = pOutliner->GetControlWord(); + nCntrl |= EEControlBits::ALLOWBIGOBJS; + + const SwViewOption *pOpt = pSh->GetViewOptions(); + + if (SwViewOption::IsFieldShadings()) + nCntrl |= EEControlBits::MARKFIELDS; + else + nCntrl &= ~EEControlBits::MARKFIELDS; + + if (pOpt->IsOnlineSpell()) + nCntrl |= EEControlBits::ONLINESPELLING; + else + nCntrl &= ~EEControlBits::ONLINESPELLING; + + pOutliner->SetControlWord(nCntrl); + const SfxPoolItem& rItem = pSh->GetDoc()->GetDefault(RES_CHRATR_LANGUAGE); + pOutliner->SetDefaultLanguage(static_cast(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(pObj)) + { + pToBeActivated = &const_cast(pVirtObj->GetReferencedObj()); + aNewTextEditOffset = pVirtObj->GetOffset(); + } + + // set in each case, thus it will be correct for all objects + static_cast(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->GetShapeBackgrd()); + 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 +{ + sal_uInt16 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 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(); + const size_t nCnt = pList->GetObjCount(); + + for (size_t i = 0; i < nCnt; ++i) + { + bRet = HasOnlyObj(pList->GetObj(i), 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 aLink = LINK(this, SwView, OnlineSpellCallback); + pOLV->ExecuteSpellPopup( aPos,&aLink ); + } + return bRet; +} + +bool SwView::IsDrawTextHyphenate() +{ + SdrView *pSdrView = m_pWrtShell->GetDrawView(); + bool bHyphenate = false; + + SfxItemSet aNewAttr( pSdrView->GetModel()->GetItemPool(), + svl::Items{} ); + 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(); + + SfxItemSet aSet( GetPool(), svl::Items{} ); + 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 000000000..c9d300039 --- /dev/null +++ b/sw/source/uibase/uiview/viewfunc.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_UIVIEW_VIEWFUNC_HXX +#define INCLUDED_SW_SOURCE_UIBASE_UIVIEW_VIEWFUNC_HXX + +#include + +#include + +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, + vcl::Window& rScrollBarBox, + 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 000000000..a84474176 --- /dev/null +++ b/sw/source/uibase/uiview/viewling.cxx @@ -0,0 +1,837 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +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 xParentWindow; + if (weld::Window* pParentWindow = rReq.GetFrameWeld()) + xParentWindow = pParentWindow->GetXWindow(); + // initialize dialog + uno::Sequence 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->nNode.GetNode().IsTextNode(); + const SwNodeIndex aPointNodeIndex( pPoint->nNode ); + sal_Int32 nPointIndex = pPoint->nContent.GetIndex(); + + // 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?" ); + if (!pTextNode || pTextNode->GetText().getLength() < nPointIndex) + nPointIndex = 0; + // restore cursor to its original position + m_pWrtShell->GetCursor()->GetPoint()->nContent.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(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( *new StringErrorInfo( 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 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(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(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 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(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(CRSR_SKIP_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()->nContent -= nRight; + pCursor->GetMark()->nContent += 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(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(m_pWrtShell.get())->HasSelection(); + OUString aTmp = GetThesaurusLookUpText( bSelection ); + + Reference< XThesaurus > xThes( ::GetThesaurus() ); + + if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) ) + SpellError( eLang ); + else + { + VclPtr 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(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 ); + m_pWrtShell->Push(); + SwRect aToFill; + + SwCursorShell *pCursorShell = m_pWrtShell.get(); + SwPaM *pCursor = pCursorShell->GetCursor(); + SwPosition aPoint(*pCursor->GetPoint()); + const SwTextNode *pNode = aPoint.nNode.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 const tmp(rPt, false); + SwContentFrame *const pContentFrame = pCursor->GetContentNode()->getLayoutFrame( + pCursorShell->GetLayout(), + &aPoint, &tmp); + if (pContentFrame) + { + SwRect aRepaint(static_cast(pContentFrame)->AutoSpell_( + *pCursor->GetContentNode()->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) + aParaText = pNode->GetText(); // this may include hidden text but that should be Ok + else + { + OSL_FAIL("text node expected but not found" ); + } + + bRet = true; + m_pWrtShell->SttSelect(); + std::unique_ptr 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(); + ScopedVclPtr pMenu; + + OUString sMenuName = bUseGrammarContext ? + OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu"); + if (TryContextMenuInterception(xPopup->GetMenu(), sMenuName, pMenu, aEvent)) + { + //! happy hacking for context menu modifying extensions of this + //! 'custom made' menu... *sigh* (code copied from sfx2 and framework) + if ( pMenu ) + { + const sal_uInt16 nId = static_cast(pMenu.get())->Execute(m_pEditWin, aPixPos); + OUString aCommand = static_cast(pMenu.get())->GetItemCommand(nId); + if (aCommand.isEmpty() ) + { + if (!ExecuteMenuCommand(dynamic_cast(*pMenu), *GetViewFrame(), nId)) + xPopup->Execute(nId); + } + else + { + SfxViewFrame *pSfxViewFrame = GetViewFrame(); + uno::Reference< frame::XFrame > xFrame; + if ( pSfxViewFrame ) + xFrame = pSfxViewFrame->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(&xPopup->GetMenu()); + 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, aStream.str().c_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( 2 ); + aArgs[0] <<= comphelper::makePropertyValue( "Frame", GetDispatcher().GetFrame()->GetFrame().GetFrameInterface() ); + aArgs[1] <<= 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 000000000..12606618f --- /dev/null +++ b/sw/source/uibase/uiview/viewmdi.cxx @@ -0,0 +1,700 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include + +sal_uInt16 SwView::m_nMoveType = NID_PGE; +sal_Int32 SwView::m_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(); + + 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(); + + { // start of SwActContext scope + SwActContext aActContext(m_pWrtShell.get()); + + long nFac = nFactor; + + const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr; + SwMasterUsrPref *pUsrPref = const_cast(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(); + 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( UseOnPage::Mirror == rDesc.GetUseOn() ) // mirrored pages + { + const SvxLRSpaceItem &rLeftLRSpace = rDesc.GetLeft().GetLRSpace(); + aPageSize.AdjustWidth(std::abs( rLeftLRSpace.GetLeft() - rLRSpace.GetLeft() ) ); + } + + if( SvxZoomType::OPTIMAL == eZoomType ) + { + 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 long nOf = DOCUMENTBORDER * 2; + long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width(); + nTmpWidth += nOf; + aPageSize.AdjustHeight(nOf ); + nFac = aWindowSize.Width() * 100 / nTmpWidth; + + if ( SvxZoomType::WHOLEPAGE == eZoomType ) + { + long nVisPercent = aWindowSize.Height() * 100 / aPageSize.Height(); + nFac = std::min( nFac, nVisPercent ); + } + } + else + { + const long nTmpWidth = bAutomaticViewLayout ? aPageSize.Width() : aRootSize.Width(); + nFac = aWindowSize.Width() * 100 / nTmpWidth; + } + } + + nFac = std::max( long( MINZOOM ), nFac ); + const sal_uInt16 nZoomFac = static_cast(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(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(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(); + + { + + SwActContext aActContext(m_pWrtShell.get()); + + if ( !GetViewFrame()->GetFrame().IsInPlace() && !bViewOnly ) + { + const bool bWeb = dynamic_cast< const SwWebView *>( this ) != nullptr; + SwMasterUsrPref *pUsrPref = const_cast(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& ppScrollbar = bHori ? m_pHScrollbar : m_pVScrollbar; + + assert(!ppScrollbar); //check beforehand! + + ppScrollbar = VclPtr::Create( pMDI, bHori ); + UpdateScrollbars(); + if(bHori) + ppScrollbar->SetScrollHdl( LINK( this, SwView, EndScrollHdl )); + else + ppScrollbar->SetScrollHdl( LINK( this, SwView, ScrollHdl )); + ppScrollbar->SetEndScrollHdl( LINK( this, SwView, EndScrollHdl )); + + ppScrollbar->EnableDrag(); + + if(GetWindow()) + InvalidateBorder(); + + if (!m_bShowAtResize) + ppScrollbar->ExtendedShow(); +} + +IMPL_LINK( SwView, MoveNavigationHdl, void*, p, void ) +{ + bool* pbNext = static_cast(p); + if ( !pbNext ) + return; + const bool bNext = *pbNext; + SwWrtShell& rSh = GetWrtShell(); + if ( NID_SRCH_REP != m_nMoveType) + { + if ( rSh.GetDrawView()->IsTextEdit() ) + rSh.EndTextEdit(); + if ( IsDrawMode() ) + LeaveDrawCreate(); + } + if ( NID_POSTIT != m_nMoveType && m_pPostItMgr ) + { + sw::annotation::SwAnnotationWin* pActiveSidebarWin = m_pPostItMgr->GetActiveSidebarWin(); + if (pActiveSidebarWin) + pActiveSidebarWin->SwitchToFieldPos(); + } + switch( m_nMoveType ) + { + case NID_PGE: + if ( bNext ) + { + if ( USHRT_MAX == rSh.GetNextPrevPageNum( true ) ) + { + rSh.GotoPage( 1, true ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); + } + else + { + PhyPageDown(); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + } + } + else + { + if ( USHRT_MAX == rSh.GetNextPrevPageNum( false ) ) + { + rSh.GotoPage( rSh.GetPageCnt(), true ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); + } + else + { + PhyPageUp(); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + } + } + 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(m_nMoveType == NID_GRF) + eType = GotoObjFlags::FlyGrf; + else if(m_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, + m_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_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) + { + m_nActMark++; + if (m_nActMark >= MAX_MARKS || m_nActMark >= static_cast(vNavMarkNames.size())) + { + m_nActMark = 0; + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderEndWrapped ); + } + } + else + { + m_nActMark--; + if (m_nActMark < 0 || m_nActMark >= static_cast(vNavMarkNames.size())) + { + m_nActMark = vNavMarkNames.size()-1; + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::ReminderStartWrapped ); + } + } + rSh.GotoMark(vNavMarkNames[m_nActMark]); + } + else + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + } + break; + + case NID_POSTIT: + { + if ( m_pPostItMgr->HasNotes() ) + { + rSh.EnterStdMode(); + sw::annotation::SwAnnotationWin* pPostIt = GetPostItMgr()->GetActiveSidebarWin(); + if (pPostIt) + GetPostItMgr()->SetActiveSidebarWin(nullptr); + SwFieldType* pFieldType = rSh.GetFieldType(0, SwFieldIds::Postit); + if ( !rSh.MoveFieldType( pFieldType, bNext ) ) + { + bNext ? (*(m_pPostItMgr->begin()))->pPostIt->GotoPos() : + (*(m_pPostItMgr->end()-1))->pPostIt->GotoPos(); + SvxSearchDialogWrapper::SetSearchLabel( bNext ? SearchLabel::EndWrapped : SearchLabel::StartWrapped ); + } + else + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); + GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT); + } + 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; + } + 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; + sal_uInt16 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 m_nMoveType; +} + +void SwView::SetMoveType(sal_uInt16 nSet) +{ + m_nMoveType = nSet; +} + +void SwView::SetActMark(sal_Int32 nSet) +{ + m_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->IsVisible( 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->IsVisible( 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 000000000..0dd9a1964 --- /dev/null +++ b/sw/source/uibase/uiview/viewport.cxx @@ -0,0 +1,1235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "viewfunc.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 long GetLeftMargin( SwView const &rView ) +{ + SvxZoomType eType = rView.GetWrtShell().GetViewOptions()->GetZoomType(); + 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, + SwScrollbar const * pScrollbar, + bool bBorder) +{ + SwWrtShell &rSh = pView->GetWrtShell(); + const Size aDocSz( rSh.GetDocSize() ); + + const long lBorder = bBorder ? DOCUMENTBORDER : DOCUMENTBORDER * 2; + const bool bHori = pScrollbar->IsHoriScroll(); + + const long lPos = pScrollbar->GetThumbPos() + (bBorder ? DOCUMENTBORDER : 0); + + long lDelta = lPos - (bHori ? rSh.VisArea().Pos().X() : rSh.VisArea().Pos().Y()); + + const 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! + 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. + +long SwView::SetHScrollMax( long lMax ) +{ + const long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2; + const long lSize = GetDocSz().Width() + lBorder - m_aVisArea.GetWidth(); + + // At negative values the document is completely visible. + // In this case, no scrolling. + return std::max( std::min( lMax, lSize ), 0L ); +} + +long SwView::SetVScrollMax( long lMax ) +{ + const long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER * 2; + long lSize = GetDocSz().Height() + lBorder - m_aVisArea.GetHeight(); + return std::max( std::min( lMax, lSize), 0L ); // 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( 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 long nTmp = GetWrtShell().IsFrameView() ? 4 : 8; + aPt.AdjustX( -(aPt.X() % nTmp) ); + aPt.AdjustY( -(aPt.Y() % nTmp) ); +#endif + aPt = GetEditWin().PixelToLogic( aPt ); + + if ( aPt == m_aVisArea.TopLeft() ) + return; + + const long lXDiff = m_aVisArea.Left() - aPt.X(); + const long lYDiff = m_aVisArea.Top() - aPt.Y(); + SetVisArea( tools::Rectangle( aPt, + Point( m_aVisArea.Right() - lXDiff, m_aVisArea.Bottom() - lYDiff ) ), + bUpdateScrollbar); +} + +void SwView::CheckVisArea() +{ + 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; + + long nYScroll = GetYScroll(); + long nDesHeight = rRect.GetHeight(); + 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, 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, 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() ) ); + } + 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( 0L, pPt->X() ) ); + } +} + +// Scrolling + +bool SwView::IsScroll( const tools::Rectangle &rRect ) const +{ + return m_bCenterCursor || m_bTopCursor || !m_aVisArea.IsInside(rRect); +} + +void SwView::Scroll( const tools::Rectangle &rRect, sal_uInt16 nRangeX, sal_uInt16 nRangeY ) +{ + if ( m_aVisArea.IsEmpty() ) + return; + + tools::Rectangle aOldVisArea( m_aVisArea ); + 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)) + { + Point aTopLeft(GetEditWin().GetSystemWindow()->OutputToAbsoluteScreenPixel(Point(x, y))); + aTopLeft = GetEditWin().AbsoluteScreenToOutputPixel(aTopLeft); + 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.IsInside( 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? + long nTopDiff = aDlgRect.Top() - m_aVisArea.Top(); + 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.IsInside( 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 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 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; + 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; + 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(0L, 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(CRSR_SKIP_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; +} + +// Handler of the scrollbars + +IMPL_LINK( SwView, ScrollHdl, ScrollBar *, p, void ) +{ + SwScrollbar* pScrollbar = static_cast(p); + if ( GetWrtShell().ActionPend() ) + return; + + if ( pScrollbar->GetType() == ScrollType::Drag ) + m_pWrtShell->EnableSmooth( false ); + + if(!m_pWrtShell->GetViewOptions()->getBrowseMode() && + pScrollbar->GetType() == ScrollType::Drag) + { + // Here comment out again if it is not desired to scroll together: + // The end scrollhandler invalidate the FN_STAT_PAGE, + // so we don't must do it again. + EndScrollHdl(pScrollbar); + + if ( !m_bWheelScrollInProgress && Help::IsQuickHelpEnabled() && + m_pWrtShell->GetViewOptions()->IsShowScrollBarTips()) + { + + Point aPos( m_aVisArea.TopLeft() ); + lcl_GetPos(this, aPos, pScrollbar, IsDocumentBorder()); + + sal_uInt16 nPhNum = 1; + sal_uInt16 nVirtNum = 1; + + OUString sDisplay; + if(m_pWrtShell->GetPageNumber( aPos.Y(), false, nPhNum, nVirtNum, sDisplay )) + { + // The end scrollhandler invalidate the FN_STAT_PAGE, + // so we don't must do it again. + // if(!GetViewFrame()->GetFrame().IsInPlace()) + // S F X_BINDINGS().Update(FN_STAT_PAGE); + + //QuickHelp: + if( m_pWrtShell->GetPageCnt() > 1 ) + { + tools::Rectangle aRect; + aRect.SetLeft( pScrollbar->GetParent()->OutputToScreenPixel( + pScrollbar->GetPosPixel() ).X() -8 ); + aRect.SetTop( pScrollbar->OutputToScreenPixel( + pScrollbar->GetPointerPosPixel() ).Y() ); + aRect.SetRight( aRect.Left() ); + aRect.SetBottom( aRect.Top() ); + + OUString sPageStr( GetPageStr( nPhNum, nVirtNum, sDisplay )); + SwContentAtPos aCnt( IsAttrAtPos::Outline ); + bool bSuccess = m_pWrtShell->GetContentAtPos(aPos, aCnt); + if (bSuccess && !aCnt.sStr.isEmpty()) + { + sPageStr += " - "; + sal_Int32 nChunkLen = std::min(aCnt.sStr.getLength(), 80); + OUString sChunk = aCnt.sStr.copy(0, nChunkLen); + sPageStr = sChunk + sPageStr; + sPageStr = sPageStr.replace('\t', ' '); + sPageStr = sPageStr.replace(0x0a, ' '); + } + nPgNum = nPhNum; + } + } + } + } + else + EndScrollHdl(pScrollbar); + + if ( pScrollbar->GetType() == ScrollType::Drag ) + m_pWrtShell->EnableSmooth( true ); +} + +// Handler of the scrollbars + +IMPL_LINK( SwView, EndScrollHdl, ScrollBar *, p, void ) +{ + SwScrollbar* pScrollbar = static_cast(p); + if ( !GetWrtShell().ActionPend() ) + { + if(nPgNum) + { + nPgNum = 0; + Help::ShowQuickHelp(pScrollbar, tools::Rectangle(), OUString()); + } + Point aPos( m_aVisArea.TopLeft() ); + bool bBorder = IsDocumentBorder(); + lcl_GetPos(this, aPos, pScrollbar, bBorder); + if ( bBorder && aPos == m_aVisArea.TopLeft() ) + UpdateScrollbars(); + else + SetVisArea( aPos, false ); + + GetViewFrame()->GetBindings().Update(FN_STAT_PAGE); + } +} + +// 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 ); + aTopLeft = GetEditWin().PixelToLogic( aTopLeft ); + Point aBottomRight( GetEditWin().PixelToLogic( aRect.BottomRight() ) ); + + aRect.SetLeft( aTopLeft.X() ); + aRect.SetTop( aTopLeft.Y() ); + aRect.SetRight( aBottomRight.X() ); + aRect.SetBottom( aBottomRight.Y() ); + + // The shifts to the right and/or below can now be incorrect + // (e.g. change zoom level, change view size). + const long lBorder = IsDocumentBorder() ? DOCUMENTBORDER : DOCUMENTBORDER*2; + if ( aRect.Left() ) + { + const long lWidth = GetWrtShell().GetDocSize().Width() + lBorder; + if ( aRect.Right() > lWidth ) + { + long lDelta = aRect.Right() - lWidth; + aRect.AdjustLeft( -lDelta ); + aRect.AdjustRight( -lDelta ); + } + } + if ( aRect.Top() ) + { + const long lHeight = GetWrtShell().GetDocSize().Height() + lBorder; + if ( aRect.Bottom() > lHeight ) + { + 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() ) + { + 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 long nTmp = rSet.GetScrollBarSize(); + if( m_pVScrollbar->IsVisible(true) ) + { + if(bRightVRuler) + rToFill.Left() = nTmp; + else + rToFill.Right() = nTmp; + } + if ( m_pHScrollbar->IsVisible(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, + vcl::Window& rScrollBarBox, + SvxRuler* pVRuler, + SvxRuler* pHRuler, + bool bVRulerRight ) +{ +// ViewResizePixel is also used by Preview!!! + + const bool bHRuler = pHRuler && pHRuler->IsVisible(); + const long nHLinSzHeight = bHRuler ? + pHRuler->GetSizePixel().Height() : 0; + const bool bVRuler = pVRuler && pVRuler->IsVisible(); + const long nVLinSzWidth = bVRuler ? + pVRuler->GetSizePixel().Width() : 0; + + const long nScrollBarSize = rRef.GetSettings().GetStyleSettings().GetScrollBarSize(); + const long nHBSzHeight = rHScrollbar.IsVisible(true) ? nScrollBarSize : 0; + const long nVBSzWidth = rVScrollbar.IsVisible(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() ); + } + + rScrollBarBox.SetPosSizePixel(aScrollFillPos, Size(nVBSzWidth, nHBSzHeight)); +} + +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->IsVisible(true); + const bool bVScrollVisible = m_pVScrollbar->IsVisible(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(), rOfst, aSz, aEditSz, *m_pVScrollbar, + *m_pHScrollbar, *m_pScrollFill, 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(); + long nZoom = 100; + if (rFrac.IsValid()) + nZoom = 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->IsVisible(true) || + bVScrollVisible != m_pVScrollbar->IsVisible(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->IsVisible(false) != bShowH && !bHAuto) + ShowHScrollbar(bShowH); + m_pHScrollbar->SetAuto( bHAuto ); + if(m_pVScrollbar->IsVisible(false) != bShowV && !bAuto) + ShowVScrollbar(bShowV); + m_pVScrollbar->SetAuto(bAuto); + + SET_CURR_SHELL( m_pWrtShell.get() ); + bool bRepeat = false; + long nCnt = 0; + + bool bUnLockView = !m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); + m_pWrtShell->LockPaint(); + + do { + ++nCnt; + const bool bScroll1 = m_pVScrollbar->IsVisible(true); + const bool bScroll2 = m_pHScrollbar->IsVisible(true); + SvBorder aBorder; + CalcAndSetBorderPixel( aBorder ); + const Size aEditSz( GetEditWin().GetOutputSizePixel() ); + ViewResizePixel( GetEditWin(), rOfst, rSize, aEditSz, *m_pVScrollbar, + *m_pHScrollbar, *m_pScrollFill, 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->IsVisible(true); + if ( !bRepeat ) + bRepeat = bScroll2 != m_pHScrollbar->IsVisible(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(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 long lOfst = bBorder ? 0 : DOCUMENTBORDER * 2; + aTmpSz.AdjustWidth(lOfst ); aTmpSz.AdjustHeight(lOfst ); + + { + const bool bVScrollVisible = m_pVScrollbar->IsVisible(true); + m_pVScrollbar->DocSzChgd( aTmpSz ); + m_pVScrollbar->ViewPortChgd( aTmpRect ); + if ( bVScrollVisible != m_pVScrollbar->IsVisible(true) ) + bRet = true; + } + { + const bool bHScrollVisible = m_pHScrollbar->IsVisible(true); + m_pHScrollbar->DocSzChgd( aTmpSz ); + m_pHScrollbar->ViewPortChgd( aTmpRect ); + if ( bHScrollVisible != m_pHScrollbar->IsVisible(true) ) + bRet = true; + m_pScrollFill->Show(m_pHScrollbar->IsVisible(true) && m_pVScrollbar->IsVisible(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()) + { + long nFact = m_pWrtShell->GetViewOptions()->GetZoom(); + if( 0L > pWData->GetDelta() ) + nFact = std::max( long(20), basegfx::zoomtools::zoomOut( nFact )); + else + nFact = std::min( long(600), 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; +} + +/* 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 000000000..5232c6b6a --- /dev/null +++ b/sw/source/uibase/uiview/viewprt.cxx @@ -0,0 +1,350 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "viewfunc.hxx" +#include +#include +#include + +#include +#include +#include + +#include + +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(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; + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_ADDPRINTER, false, + reinterpret_cast(&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 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 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( 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 xInfoBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(), + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_ERR_NO_FAX))); + const char* 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(SID_SILENT); + bool bSilent = pSilentItem && pSilentItem->GetValue(); + const SfxBoolItem* pPrintFromMergeItem = rReq.GetArg(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 xBuilder(Application::CreateBuilder(GetEditWin().GetFrameWeld(), "modules/swriter/ui/printmergedialog.ui")); + std::unique_ptr 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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwView")); + SfxViewShell::dumpAsXml(pWriter); + if (m_pWrtShell) + m_pWrtShell->dumpAsXml(pWriter); + 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); +} + +// Create page printer/additions for SwView and SwPagePreview + +std::unique_ptr 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 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 ) ) + { + // Close application own printing options in SfxPrinter. + SwAddPrinterItem aAddPrinterItem(aPrtData); + SfxItemSet aSet( + pSh->GetAttrPool(), + svl::Items< + 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>{}); + + utl::MiscCfg aMisc; + + if(bWeb) + aSet.Put(SfxUInt16Item(SID_HTML_MODE, + ::GetHtmlMode(static_cast(pSh)->GetView().GetDocShell()))); + aSet.Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN, + aMisc.IsNotFoundWarning() )); + aSet.Put(aAddPrinterItem); + aSet.Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, + static_cast(aMisc.IsPaperSizeWarning() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) | + static_cast(aMisc.IsPaperOrientationWarning() ? 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 000000000..440b77ad7 --- /dev/null +++ b/sw/source/uibase/uiview/viewsrch.cxx @@ -0,0 +1,869 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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& 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. + if (SwPaM* pPaM = pWrtShell->GetCursor()) + { + std::vector aMatches; + for (SwPaM& rPaM : pPaM->GetRingContainer()) + { + if (SwShellCursor* pShellCursor = dynamic_cast(&rPaM)) + { + std::vector aSelectionRectangles; + pShellCursor->SwSelPaintRects::Show(&aSelectionRectangles); + std::vector 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", aMatches); + + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTree); + OString aPayload = aStream.str().c_str(); + + pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_RESULT_SELECTION, aPayload.getStr()); + } +} + +void SwView::ExecSearch(SfxRequest& rReq) +{ + 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( 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(); + + DELETEZ( s_pSearchList ); + DELETEZ( s_pReplaceList ); + + SvxSearchDialog *const pSrchDlg(GetSearchDialog()); + if (pSrchDlg) + { + // We will remember the search-/replace items. + const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList(); + if( nullptr != pList && pList->Count() ) + s_pSearchList = new SearchAttrItemList( *pList ); + + pList = pSrchDlg->GetReplaceItemList(); + if (nullptr != pList && pList->Count()) + s_pReplaceList = 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) + { + DELETEZ( s_pSearchList ); + DELETEZ( s_pReplaceList ); + + const SearchAttrItemList* pList = pSrchDlg->GetSearchItemList(); + if( nullptr != pList && pList->Count() ) + s_pSearchList = new SearchAttrItemList( *pList ); + + pList = pSrchDlg->GetReplaceItemList(); + if (nullptr != pList && pList->Count()) + s_pReplaceList = 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)); + } + break; + case SvxSearchCmd::FIND_ALL: + { + // Disable LOK selection notifications during search. + m_pWrtShell->GetSfxViewShell()->setTiledSearching(true); + bool bRet = SearchAll(); + m_pWrtShell->GetSfxViewShell()->setTiledSearching(false); + + if( !bRet ) + { +#if HAVE_FEATURE_DESKTOP + if( !bQuiet ) + { + m_pWrtShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SEARCH_NOT_FOUND, s_pSrchItem->GetSearchString().toUtf8().getStr()); + SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); + } +#endif + s_bFound = false; + } + else if (comphelper::LibreOfficeKit::isActive()) + lcl_emitSearchResultCallbacks(s_pSrchItem, m_pWrtShell.get(), /* bHighlightAll = */ true); + rReq.SetReturnValue(SfxBoolItem(nSlot, bRet)); + } + 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_pReplaceList ) + { + // 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 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_pReplaceList ) + 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().getStr()); + 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 sal_uInt16 aNormalAttr[] = + { +/* 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, +/*22 */ RES_LR_SPACE, RES_UL_SPACE, +/*24 */ SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP, +/*26 */ 0 + }; + + SfxItemSet aSet(m_pWrtShell->GetAttrPool(), aNormalAttr); + + if( SW_MOD()->GetCTLOptions().IsCTLFontEnabled() ) + { + aSet.MergeRange(RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_WEIGHT); + } + SvtCJKOptions aCJKOpt; + if( aCJKOpt.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); + } + + sal_uInt16 nWhich = SID_SEARCH_SEARCHSET; + + if ( FID_SEARCH_REPLACESET == nSlot ) + { + nWhich = SID_SEARCH_REPLACESET; + + if ( s_pReplaceList ) + { + s_pReplaceList->Get( aSet ); + DELETEZ( s_pReplaceList ); + } + } + else if ( s_pSearchList ) + { + s_pSearchList->Get( aSet ); + DELETEZ( s_pSearchList ); + } + 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::unique_ptr pWait(new SwWait( *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; + } + pWait.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().getStr()); + 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); + pWait.reset(new SwWait( *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(); + pWait.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().getStr()); + SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::NotFound); + } +#endif + return s_bFound; +} + +bool 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 = static_cast(FUNC_Search( aOpts )); + s_bFound = 0 != nFound; + + m_pWrtShell->EndAllAction(); + return s_bFound; +} + +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->GetSwCursor()->Start(); + SwPosition aEndPos = * m_pWrtShell->GetSwCursor()->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->GetSwCursor()->Start()) = aStartPos; + (* m_pWrtShell->GetSwCursor()->End()) = aEndPos; + } + else + { + (* m_pWrtShell->GetSwCursor()->Start()) = aEndPos; + (* m_pWrtShell->GetSwCursor()->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_pReplaceList && s_pReplaceList->Count() && m_pWrtShell->HasSelection() ) + { + SfxItemSet aReplSet( m_pWrtShell->GetAttrPool(), + aTextFormatCollSetRange ); + if( s_pReplaceList->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 sal_uInt16 aSearchAttrRange[] = { + RES_FRMATR_BEGIN, RES_FRMATR_END-1, + RES_CHRATR_BEGIN, RES_CHRATR_END-1, + RES_PARATR_BEGIN, RES_PARATR_END-1, + SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP, + 0 }; + + SfxItemSet aSrchSet( m_pWrtShell->GetAttrPool(), aSearchAttrRange); + if( s_pSearchList && s_pSearchList->Count() ) + { + s_pSearchList->Get( aSrchSet ); + + // -- Page break with page template + ::SfxToSwPageDescAttr( *m_pWrtShell, aSrchSet ); + } + + std::unique_ptr pReplSet; + if( bDoReplace && s_pReplaceList && s_pReplaceList->Count() ) + { + pReplSet.reset( new SfxItemSet( m_pWrtShell->GetAttrPool(), + aSearchAttrRange ) ); + s_pReplaceList->Get( *pReplSet ); + + // -- Page break with page template + ::SfxToSwPageDescAttr( *m_pWrtShell, *pReplSet ); + + if( !pReplSet->Count() ) // too bad, we don't know + pReplSet.reset(); // the attributes + } + + // build SearchOptions to be used + + i18nutil::SearchOptions2 aSearchOpt( s_pSrchItem->GetSearchOptions() ); + aSearchOpt.Locale = GetAppLanguageTag().getLocale(); + if( !bDoReplace ) + aSearchOpt.replaceString.clear(); + + sal_uLong nFound; + if( aSrchSet.Count() || ( pReplSet && pReplSet->Count() )) + { + nFound = m_pWrtShell->SearchAttr( + aSrchSet, + !s_pSrchItem->GetPattern(), + rOptions.eStart, + rOptions.eEnd, + eRanges, + !s_pSrchItem->GetSearchString().isEmpty() ? &aSearchOpt : nullptr, + pReplSet.get() ); + } + 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(); + SvxSearchDialogWrapper *pWrp = static_cast( SfxViewFrame::Current()->GetChildWindow(nId) ); + auto pSrchDlg = pWrp ? pWrp->getDialog() : nullptr; + return pSrchDlg; +#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(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 000000000..caa3bd34a --- /dev/null +++ b/sw/source/uibase/uiview/viewstat.cxx @@ -0,0 +1,603 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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( this ) != nullptr; + + while(nWhich) + { + switch(nWhich) + { + case FN_NAV_ELEMENT: + // used to update all instances of this control + rSet.InvalidateItem( nWhich ); + 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="; + if (rDesc.GetLandscape()) + { + aPayload += "IsLandscape"; + } + else + { + aPayload += "IsPortrait"; + } + libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload.getStr()); + } + } + 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 SfxPoolItem* pState = m_pShell->GetSlotState(SID_UNDO); + if(pState) + rSet.Put(*pState); + 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, + static_cast(::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() ) ); + 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* pVFrame = GetViewFrame(); + if (pVFrame->KnowsChildWindow(nWhich)) + rSet.Put(SfxBoolItem( nWhich, pVFrame->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(; index < table.size(); ++index ) + { + const SwRangeRedline* tmp = table[ index ]; + if( *tmp->Start() >= *pCursor->End()) + 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. + if (nullptr == pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), nullptr)) + 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="); + SwRedlineTable::size_type nRedline = 0; + if (pDoc->getIDocumentRedlineAccess().GetRedline(*pCursor->Start(), &nRedline)) + aPayload += OString::number(nRedline); + libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, aPayload.getStr()); + } + } + 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 long nBottom = m_pWrtShell->GetDocSize().Height() + DOCUMENTBORDER; + const 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(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 ); + 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 + const SfxPoolItem* pState = nullptr; + if(nAlias) + GetViewFrame()->GetDispatcher()->QueryState( nAlias, pState ); + if(pState) + { + if (!(m_nSelectionType & SelectionType::DrawObject)) + { + rSet.Put(pState->CloneSetWhich(nWhich)); + } + } + else + rSet.DisableItem(nWhich); + } + break; + } + nWhich = aIter.NextWhich(); + } +} + +void SwView::GetDrawState(SfxItemSet &rSet) +{ + SfxWhichIter aIter(rSet); + bool bWeb = dynamic_cast( 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 + rSet.Put( SfxBoolItem( nWhich, m_nDrawSfxId == nWhich ) ); + break; + + case SID_DRAW_TEXT_VERTICAL: + case SID_DRAW_CAPTION_VERTICAL: + if ( bWeb || !SvtLanguageOptions().IsVerticalTextEnabled() ) + rSet.DisableItem( nWhich ); + else + 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 000000000..b7f6e02dc --- /dev/null +++ b/sw/source/uibase/uiview/viewtab.cxx @@ -0,0 +1,2532 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +// Pack columns +static void lcl_FillSvxColumn(const SwFormatCol& rCol, + long nTotalWidth, + SvxColumnItem& rColItem, + long nDistance) +{ + const SwColumns& rCols = rCol.GetColumns(); + + bool bOrtho = rCol.IsOrtho() && !rCols.empty(); + 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(); + } + + long nWidth = 0; + for ( size_t i = 0; i < rCols.size(); ++i ) + { + const SwColumn* pCol = &rCols[i]; + const 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 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, + 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 long nStart = std::max(rColItem[i+1].nStart, rColItem[i].nEnd); + const sal_uInt16 nRight = static_cast((nStart - rColItem[i].nEnd) / 2); + + const long nWidth = rColItem[i].nEnd - rColItem[i].nStart + nLeft + nRight; + + SwColumn* pCol = &rArr[i]; + pCol->SetWishWidth( sal_uInt16(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() - static_cast(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 ) + { + 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(long& nVal, long nScale) +{ + nVal *= nScale; + nVal >>= 8; +} + +static void ResizeFrameCols(SwFormatCol& rCol, + long nOldWidth, + long nNewWidth, + long nLeftDelta ) +{ + SwColumns& rArr = rCol.GetColumns(); + long nWishSum = static_cast(rCol.GetWishWidth()); + long nWishDiff = (nWishSum * 100/nOldWidth * nNewWidth) / 100 - nWishSum; + long nNewWishWidth = nWishSum + nWishDiff; + if(nNewWishWidth > 0xffffl) + { + // If the desired width is getting too large, then all values + // must be scaled appropriately. + long nScale = (0xffffl << 8)/ nNewWishWidth; + for(SwColumn & i : rArr) + { + SwColumn* pCol = &i; + long nVal = pCol->GetWishWidth(); + lcl_Scale(nVal, nScale); + pCol->SetWishWidth(static_cast(nVal)); + nVal = pCol->GetLeft(); + lcl_Scale(nVal, nScale); + pCol->SetLeft(static_cast(nVal)); + nVal = pCol->GetRight(); + lcl_Scale(nVal, nScale); + pCol->SetRight(static_cast(nVal)); + } + lcl_Scale(nNewWishWidth, nScale); + lcl_Scale(nWishDiff, nScale); + } + rCol.SetWishWidth( static_cast(nNewWishWidth) ); + + if( nLeftDelta >= 2 || nLeftDelta <= -2) + rArr.front().SetWishWidth(rArr.front().GetWishWidth() + static_cast(nWishDiff)); + else + rArr.back().SetWishWidth(rArr.back().GetWishWidth() + static_cast(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(rHeaderFormat.GetHeaderFormat()); + + const SwFormatFooter& rFooterFormat = rDesc.GetMaster().GetFooter(); + SwFrameFormat *pFooterFormat = const_cast(rFooterFormat.GetFooterFormat()); + + const SwFormatFrameSize &rFrameSize = rDesc.GetMaster().GetFrameSize(); + + const SwRect& rPageRect = rSh.GetAnyCurRect(CurRectType::Page); + const long nPageWidth = bBrowse ? rPageRect.Width() : rFrameSize.GetWidth(); + const 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( static_cast(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); + } + long nDeltaX = bVerticalFrame ? + rRect.Right() - rPageRect.Right() + aLongLR.GetRight() : + rPageRect.Left() + aLongLR.GetLeft() - rRect.Left(); + + SfxItemSet aSet( GetPool(), svl::Items{} ); + + 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() ); + long nOldWidth = aSize.GetWidth(); + + if(aSize.GetWidthPercent()) + { + SwRect aRect; + rSh.CalcBoundRect(aRect, RndStdIds::FLY_AS_CHAR); + 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 + 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(); + long nLeftDiff = aLongLR.GetLeft() - static_cast(aSectRect.Left() - rPageRect.Left() ); + long nRightDiff = aLongLR.GetRight() - static_cast( 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); + SfxItemSet aSet(rSh.GetAttrPool(), svl::Items{}); + aSet.Put(aLRTmp); + //change the first/last column + if(bSect) + { + SwFormatCol aCols( pSectFormat->GetCol() ); + 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( static_cast(pReqArgs-> + Get( SID_ATTR_LONG_ULSPACE ))); + + if( bFrameSelection || nFrameType & FrameTypeFlags::FLY_ANY ) + { + SwFrameFormat* pFormat = rSh.GetFlyFrameFormat(); + const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded); + const long nDeltaY = rPageRect.Top() + aLongULSpace.GetUpper() - rRect.Top(); + const long nHeight = nPageHeight - (aLongULSpace.GetUpper() + aLongULSpace.GetLower()); + + SfxItemSet aSet( GetPool(), svl::Items{} ); + //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); + 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 long nLeftDiff = aLongULSpace.GetUpper() - static_cast(aSectRect.Top() - rPageRect.Top()); + const long nRightDiff = aLongULSpace.GetLower() - static_cast(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); + SfxItemSet aSet(rSh.GetAttrPool(), svl::Items{}); + aSet.Put(aLR); + //change the first/last column + if(bSect) + { + SwFormatCol aCols( pSectFormat->GetCol() ); + 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( static_cast(aLongULSpace.GetUpper()) ); + else + aUL.SetLower( static_cast(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(static_cast(aLongULSpace.GetUpper())); + aUL.SetLower(static_cast(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(static_cast(aLongULSpace.GetUpper())); + aUL.SetLower(static_cast(aLongULSpace.GetLower())); + aDesc.GetMaster().SetFormatAttr(aUL); + } + rSh.ChgPageDesc( nDescId, aDesc ); + } + break; + + case SID_ATTR_PAGE_COLUMN: + if ( pReqArgs ) + { + const SfxInt16Item aColumnItem( static_cast(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 long nLeft = aLR.GetLeft(); + const long nRight = aLR.GetRight(); + const 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 ); + + long nColumnLeft = 0; + long nColumnRight = 0; + if ( nPageColumnType == 4 ) + { + nColumnRight = static_cast(nWidth/3); + nColumnLeft = nWidth - nColumnRight; + aCols.GetColumns()[0].SetWishWidth( nColumnLeft ); + aCols.GetColumns()[1].SetWishWidth( nColumnRight ); + } + else if ( nPageColumnType == 5 ) + { + nColumnLeft = static_cast(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(pReqArgs-> + Get( nWhich ))); + aTabStops.SetWhich(RES_PARATR_TABSTOP); + const SvxTabStopItem& rDefTabs = rSh.GetDefault(RES_PARATR_TABSTOP); + + // Default tab at pos 0 + SfxItemSet aSet( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aSet ); + const SvxLRSpaceItem& rLR = aSet.Get(RES_LR_SPACE); + + if ( rLR.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->IsAutoUpdateFormat() ) + { + SfxItemSet aTmp(GetPool(), svl::Items{}); + 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(pReqArgs->Get(SID_TABSTOP_ATTR_INDEX)); + const auto aPositionItem = static_cast(pReqArgs->Get(SID_TABSTOP_ATTR_POSITION)); + const auto aRemoveItem = static_cast(pReqArgs->Get(SID_TABSTOP_ATTR_REMOVE)); + const sal_Int32 nIndex = aIndexItem.GetValue(); + const sal_Int32 nPosition = aPositionItem.GetValue(); + const bool bRemove = aRemoveItem.GetValue(); + + + + SfxItemSet aItemSet(GetPool(), svl::Items{}); + 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: + { + const SfxPoolItem *fLineIndent, *pLeftIndent, *pRightIndent; + if (pReqArgs) + { + SfxItemSet aLRSpaceSet( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aLRSpaceSet ); + SvxLRSpaceItem aParaMargin( aLRSpaceSet.Get( RES_LR_SPACE ) ); + + if (pReqArgs->GetItemState(SID_PARAGRAPH_FIRST_LINE_INDENT,true,&fLineIndent) == SfxItemState::SET) + { + const OUString ratio = static_cast(fLineIndent)->GetValue(); + aParaMargin.SetTextFirstLineOffset(nPageWidth * ratio.toFloat()); + } + else if (pReqArgs->GetItemState(SID_PARAGRAPH_LEFT_INDENT,true,&pLeftIndent) == SfxItemState::SET) + { + const OUString ratio = static_cast(pLeftIndent)->GetValue(); + aParaMargin.SetLeft(nPageWidth * ratio.toFloat()); + } + else if (pReqArgs->GetItemState(SID_PARAGRAPH_RIGHT_INDENT,true,&pRightIndent) == SfxItemState::SET) + { + const OUString ratio = static_cast(pRightIndent)->GetValue(); + aParaMargin.SetRight(nPageWidth * ratio.toFloat()); + } + rSh.SetAttrItem(aParaMargin); + } + break; + } + case SID_HANGING_INDENT: + { + SfxItemSet aLRSpaceSet( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aLRSpaceSet ); + SvxLRSpaceItem aParaMargin( aLRSpaceSet.Get( RES_LR_SPACE ) ); + + SvxLRSpaceItem aNewMargin( RES_LR_SPACE ); + aNewMargin.SetTextLeft( aParaMargin.GetTextLeft() + aParaMargin.GetTextFirstLineOffset() ); + aNewMargin.SetRight( aParaMargin.GetRight() ); + aNewMargin.SetTextFirstLineOffset( (aParaMargin.GetTextFirstLineOffset()) * -1 ); + + rSh.SetAttrItem( aNewMargin ); + break; + } + + case SID_ATTR_PARA_LRSPACE_VERTICAL: + case SID_ATTR_PARA_LRSPACE: + if ( pReqArgs ) + { + SvxLRSpaceItem aParaMargin(static_cast(pReqArgs->Get(nSlot))); + + aParaMargin.SetRight( aParaMargin.GetRight() - m_nRightBorderDistance ); + aParaMargin.SetTextLeft(aParaMargin.GetTextLeft() - m_nLeftBorderDistance ); + + aParaMargin.SetWhich( RES_LR_SPACE ); + SwTextFormatColl* pColl = rSh.GetCurTextFormatColl(); + + // #i23726# + if (m_pNumRuleNodeFromDoc) + { + // --> #i42922# Mouse move of numbering label + // has to consider the left indent of the paragraph + SfxItemSet aSet( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aSet ); + const SvxLRSpaceItem& rLR = aSet.Get(RES_LR_SPACE); + + SwPosition aPos(*m_pNumRuleNodeFromDoc); + // #i90078# + rSh.SetIndent( static_cast< short >(aParaMargin.GetTextLeft() - rLR.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->IsAutoUpdateFormat() ) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + aSet.Put(aParaMargin); + rSh.AutoUpdatePara( pColl, aSet); + } + else + rSh.SetAttrItem( aParaMargin ); + + if ( aParaMargin.GetTextFirstLineOffset() < 0 ) + { + SfxItemSet aSet( GetPool(), svl::Items{} ); + + 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 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->IsAutoUpdateFormat()) + { + SfxItemSet aSetTmp(GetPool(), svl::Items{}); + aSetTmp.Put(*aTabStops); + rSh.AutoUpdatePara( pColl, aSetTmp ); + } + else + rSh.SetAttrItem( *aTabStops ); + } + } + } + break; + + case SID_ATTR_PARA_ULSPACE: + if ( pReqArgs ) + { + SvxULSpaceItem aParaMargin(static_cast(pReqArgs->Get(nSlot))); + + aParaMargin.SetUpper( aParaMargin.GetUpper() ); + aParaMargin.SetLower(aParaMargin.GetLower()); + + aParaMargin.SetWhich( RES_UL_SPACE ); + SwTextFormatColl* pColl = rSh.GetCurTextFormatColl(); + if( pColl && pColl->IsAutoUpdateFormat() ) + { + SfxItemSet aSet(GetPool(), svl::Items{}); + aSet.Put(aParaMargin); + rSh.AutoUpdatePara( pColl, aSet); + } + else + rSh.SetAttrItem( aParaMargin ); + } + break; + case SID_PARASPACE_INCREASE: + case SID_PARASPACE_DECREASE: + { + SfxItemSet aULSpaceSet( GetPool(), svl::Items{} ); + 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->IsAutoUpdateFormat() ) + { + aULSpaceSet.Put( aULSpace ); + rSh.AutoUpdatePara( pColl, aULSpaceSet ); + } + else + rSh.SetAttrItem( aULSpace, SetAttrMode::DEFAULT, true ); + } + break; + + case SID_RULER_CHANGE_STATE: + { + const SfxPoolItem *pMargin1, *pMargin2; + if ( pReqArgs && + pReqArgs->GetItemState(SID_RULER_MARGIN1,true,&pMargin1) == SfxItemState::SET ) + { + const OUString ratio = static_cast(pMargin1)->GetValue(); + GetHRuler().SetValues(RulerChangeType::MARGIN1, GetHRuler().GetPageWidth() * ratio.toFloat()); + } + else if ( pReqArgs && + pReqArgs->GetItemState(SID_RULER_MARGIN2,true,&pMargin2) == SfxItemState::SET ) + { + const OUString ratio = static_cast(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(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 + long nBorder = static_cast(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; + SfxItemSet aSet( GetPool(), svl::Items{} ); + 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 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(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 + { + 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]; + 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; + const SfxPoolItem* pSingleLine; + if( SfxItemState::SET == rReq.GetArgs()->GetItemState(SID_RULER_ACT_LINE_ONLY, false, &pSingleLine)) + bSingleLine = static_cast(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 SfxPoolItem *pBorderType; + const SfxPoolItem *pIndex; + const SfxPoolItem *pOffset; + constexpr long constDistanceOffset = 40; + + if (pReqArgs->GetItemState(SID_TABLE_BORDER_TYPE, true, &pBorderType) == SfxItemState::SET + && pReqArgs->GetItemState(SID_TABLE_BORDER_INDEX, true, &pIndex) == SfxItemState::SET + && pReqArgs->GetItemState(SID_TABLE_BORDER_OFFSET, true, &pOffset) == SfxItemState::SET) + { + const OUString sType = static_cast(pBorderType)->GetValue(); + const sal_uInt16 nIndex = static_cast(pIndex)->GetValue(); + const sal_Int32 nOffset = static_cast(pOffset)->GetValue(); + + if (sType.startsWith("column")) + { + SwTabCols aTabCols; + rSh.GetTabCols(aTabCols); + + if (sType == "column-left") + { + auto & rEntry = aTabCols.GetEntry(0); + long nNewPosition = aTabCols.GetLeft() + long(nOffset); + long nPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset); + aTabCols.SetLeft(nPosition); + } + else if (sType == "column-right") + { + auto & rEntry = aTabCols.GetEntry(aTabCols.Count() - 1); + long nNewPosition = aTabCols.GetRight() + long(nOffset); + long nPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset); + aTabCols.SetRight(nPosition); + } + else if (sType == "column-middle" && nIndex < aTabCols.Count()) + { + auto & rEntry = aTabCols.GetEntry(nIndex); + long nNewPosition = rEntry.nPos + long(nOffset); + long nPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset); + rEntry.nPos = nPosition; + } + + rSh.SetTabCols(aTabCols, false); + } + else if (sType.startsWith("row")) + { + SwTabCols aTabRows; + rSh.GetTabRows(aTabRows); + + if (sType == "row-left") + { + auto & rEntry = aTabRows.GetEntry(0); + long nNewPosition = aTabRows.GetLeft() + long(nOffset); + long nPosition = std::min(nNewPosition, rEntry.nPos - constDistanceOffset); + aTabRows.SetLeft(nPosition); + } + else if (sType == "row-right") + { + auto & rEntry = aTabRows.GetEntry(aTabRows.Count() - 1); + long nNewPosition = aTabRows.GetRight() + long(nOffset); + long nPosition = std::max(nNewPosition, rEntry.nPos + constDistanceOffset); + aTabRows.SetRight(nPosition); + } + else if (sType == "row-middle" && nIndex < aTabRows.Count()) + { + auto & rEntry = aTabRows.GetEntry(nIndex); + long nNewPosition = rEntry.nPos + long(nOffset); + long nPosition = std::clamp(nNewPosition, rEntry.nMin, rEntry.nMax - constDistanceOffset); + rEntry.nPos = nPosition; + } + + rSh.SetTabRows(aTabRows, false); + } + } + } + } + break; + case SID_ATTR_PAGE_HEADER: + { + if ( pReqArgs ) + { + const bool bHeaderOn = static_cast(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 = static_cast(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(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 = static_cast(pReqArgs->Get(SID_ATTR_PAGE_HEADER_SPACING)); + SwPageDesc aDesc(rDesc); + SvxULSpaceItem aUL(0, aLongUL.GetLower(), RES_UL_SPACE ); + SwFrameFormat* pFormat = const_cast(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 = static_cast(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(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 = static_cast(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(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 = static_cast(pReqArgs->Get(SID_ATTR_PAGE_FOOTER_SPACING)); + SwPageDesc aDesc(rDesc); + SvxULSpaceItem aUL(aLongUL.GetUpper(), 0, RES_UL_SPACE ); + SwFrameFormat* pFormat = const_cast(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 = static_cast(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 long nPageWidth = rPageRect.Width(); + const 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 ); + + SfxItemSet aCoreSet( GetPool(), svl::Items{} ); + // get also the list level indent values merged as LR-SPACE item, 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((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(aUL.GetUpper()), + static_cast(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(aUL.GetUpper()), + static_cast(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 ) || + ( SfxItemState::DEFAULT > aCoreSet.GetItemState(RES_LR_SPACE) ) || + (!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 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, aStream.str().c_str()); + } + } + break; + } + + case SID_HANGING_INDENT: + { + SfxItemState e = aCoreSet.GetItemState(RES_LR_SPACE); + 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 aLR(std::make_shared(RES_LR_SPACE)); + if ( !IsTabColFromDoc() ) + { + aLR.reset(aCoreSet.Get(RES_LR_SPACE).Clone()); + + // #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; + 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()); + } + else + { + SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER ); + aCoreSet.Put( aBoxInfo ); + rSh.GetFlyFrameAttr( aCoreSet ); + const SvxBoxItem& rBox = aCoreSet.Get(RES_BOX); + aDistLR.SetLeft(rBox.GetDistance(SvxBoxItemLine::LEFT)); + aDistLR.SetRight(rBox.GetDistance(SvxBoxItemLine::RIGHT)); + + //add the paragraph border distance + SfxItemSet aCoreSet1( GetPool(), svl::Items{} ); + 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)); + } + rSet.Put(aDistLR); + 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 ) ) ) + { + SfxItemSet aCoreSet2( GetPool(), + svl::Items{} ); + 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)); + + //add the border distance of the paragraph + SfxItemSet aCoreSet1( GetPool(), svl::Items{} ); + 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)); + rSet.Put(aDistLR); + 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(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(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)); + } + + //add the border distance of the paragraph + SfxItemSet aCoreSetTmp( GetPool(), svl::Items{} ); + rSh.GetCurAttr( aCoreSetTmp ); + const SvxBoxItem& rParaBox = aCoreSetTmp.Get(RES_BOX); + aDistLR.SetLeft(aDistLR.GetLeft() + rParaBox.GetDistance(SvxBoxItemLine::LEFT)); + aDistLR.SetRight(aDistLR.GetRight() + rParaBox.GetDistance(SvxBoxItemLine::RIGHT)); + rSet.Put(aDistLR); + 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); + + long nStart = 0; + 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 (static_cast( aRect.Left() - rPageRect.Left() )); + aColItem.SetRight(static_cast( 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 long lWidth = bUseVertical ? rSizeRect.Height() : rSizeRect.Width(); + const SwRect &rRect = rSh.GetAnyCurRect(CurRectType::FlyEmbedded, pPt); + 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); + long nDist = rBox.GetSmallestDistance(); + + lcl_FillSvxColumn( + aCol, + bVerticalWriting ? aPrtRect.Height() : aPrtRect.Width(), + aColItem, nDist); + + if(bBrowse) + { + if (bVerticalWriting) + { + aColItem.SetLeft(static_cast(rPagePrtRect.Top())); + aColItem.SetRight(sal_uInt16(nPageHeight - rPagePrtRect.Bottom())); + } + else + { + aColItem.SetLeft(static_cast(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); + + long nStart = 0; + 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(0L, aTabCols.GetRight() - rEntry.nMax), + std::max(0L, 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 = static_cast(aRect.Width()); + // The entire frame width - The difference is twice the distance to the edge. + const sal_uInt16 nOuterWidth = static_cast(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 = static_cast(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( static_cast(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 + { + 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* rLR = static_cast( + rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_LRSPACE)); + const SvxULSpaceItem* rUL = static_cast( + rHeader.GetHeaderFormat()->GetAttrSet().GetItem(SID_ATTR_ULSPACE)); + SvxLongLRSpaceItem aLR(rLR->GetLeft(), rLR->GetRight(), SID_ATTR_PAGE_HEADER_LRMARGIN); + rSet.Put(aLR); + SvxLongULSpaceItem aUL( rUL->GetUpper(), rUL->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(bShared)<<1) + static_cast(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) + { + const SvxLRSpaceItem* rLR = rFooter.GetFooterFormat()->GetAttrSet().GetItem(SID_ATTR_LRSPACE); + const SvxULSpaceItem* rUL = rFooter.GetFooterFormat()->GetAttrSet().GetItem(SID_ATTR_ULSPACE); + SvxLongLRSpaceItem aLR(rLR->GetLeft(), rLR->GetRight(), SID_ATTR_PAGE_FOOTER_LRMARGIN); + rSet.Put(aLR); + 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(bShared)<<1) + static_cast(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: + { + SfxItemSet aSet = rDesc.GetMaster().GetAttrSet(); + if (const auto pFillStyleItem = aSet.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 = aSet.GetItem(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 XGradient& xGradient = aSet.GetItem( XATTR_FILLGRADIENT )->GetGradientValue(); + XFillGradientItem aFillGradientItem( OUString(), xGradient, SID_ATTR_PAGE_GRADIENT ); + rSet.Put( aFillGradientItem ); + } + break; + + case drawing::FillStyle_HATCH: + { + const XFillHatchItem *pFillHatchItem( aSet.GetItem( 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 = aSet.GetItem( 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 000000000..a644a019c --- /dev/null +++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx @@ -0,0 +1,1508 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include + +#include +#include "SwXDocumentSettings.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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_FLOATTABLE_NOMARGINS, + 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_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, +}; + +} + +static MasterPropertySetInfo * lcl_createSettingsInfo() +{ + static PropertyInfo const aWriterSettingsInfoMap[] = + { + { OUString("ForbiddenCharacters"), HANDLE_FORBIDDEN_CHARS, cppu::UnoType::get(), 0}, + { OUString("LinkUpdateMode"), HANDLE_LINK_UPDATE_MODE, cppu::UnoType::get(), 0}, + { OUString("FieldAutoUpdate"), HANDLE_FIELD_AUTO_UPDATE, cppu::UnoType::get(), 0}, + { OUString("ChartAutoUpdate"), HANDLE_CHART_AUTO_UPDATE, cppu::UnoType::get(), 0}, + { OUString("AddParaTableSpacing"), HANDLE_ADD_PARA_TABLE_SPACING, cppu::UnoType::get(), 0}, + { OUString("AddParaTableSpacingAtStart"), HANDLE_ADD_PARA_TABLE_SPACING_AT_START, cppu::UnoType::get(), 0}, + { OUString("AlignTabStopPosition"), HANDLE_ALIGN_TAB_STOP_POSITION, cppu::UnoType::get(), 0}, + { OUString("PrinterName"), HANDLE_PRINTER_NAME, cppu::UnoType::get(), 0}, + { OUString("PrinterSetup"), HANDLE_PRINTER_SETUP, cppu::UnoType< cppu::UnoSequenceType >::get(), 0}, + { OUString("PrinterPaperFromSetup"), HANDLE_PRINTER_PAPER, cppu::UnoType::get(), 0}, + { OUString("IsKernAsianPunctuation"), HANDLE_IS_KERN_ASIAN_PUNCTUATION, cppu::UnoType::get(), 0}, + { OUString("CharacterCompressionType"), HANDLE_CHARACTER_COMPRESSION_TYPE, cppu::UnoType::get(), 0}, + { OUString("ApplyUserData"), HANDLE_APPLY_USER_DATA, cppu::UnoType::get(), 0 }, + { OUString("SaveThumbnail"), HANDLE_SAVE_THUMBNAIL, cppu::UnoType::get(), 0 }, + { OUString("SaveGlobalDocumentLinks"), HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS, cppu::UnoType::get(), 0}, + { OUString("CurrentDatabaseDataSource"), HANDLE_CURRENT_DATABASE_DATA_SOURCE, cppu::UnoType::get(), 0}, + { OUString("CurrentDatabaseCommand"), HANDLE_CURRENT_DATABASE_COMMAND, cppu::UnoType::get(), 0}, + { OUString("CurrentDatabaseCommandType"), HANDLE_CURRENT_DATABASE_COMMAND_TYPE, cppu::UnoType::get(), 0}, + { OUString("EmbeddedDatabaseName"), HANDLE_EMBEDDED_DATABASE_NAME, cppu::UnoType::get(), 0}, + { OUString("SaveVersionOnClose"), HANDLE_SAVE_VERSION_ON_CLOSE, cppu::UnoType::get(), 0}, + { OUString("UpdateFromTemplate"), HANDLE_UPDATE_FROM_TEMPLATE, cppu::UnoType::get(), 0}, + + { OUString("PrinterIndependentLayout"), HANDLE_PRINTER_INDEPENDENT_LAYOUT, cppu::UnoType::get(), 0}, + { OUString("IsLabelDocument"), HANDLE_IS_LABEL_DOC, cppu::UnoType::get(), 0}, + { OUString("AddFrameOffsets"), HANDLE_IS_ADD_FLY_OFFSET, cppu::UnoType::get(), 0}, + { OUString("AddVerticalFrameOffsets"), HANDLE_IS_ADD_VERTICAL_FLY_OFFSET, cppu::UnoType::get(), 0}, + { OUString("AddExternalLeading"), HANDLE_IS_ADD_EXTERNAL_LEADING, cppu::UnoType::get(), 0}, + { OUString("UseOldNumbering"), HANDLE_OLD_NUMBERING, cppu::UnoType::get(), 0}, + { OUString("OutlineLevelYieldsNumbering"), HANDLE_OUTLINELEVEL_YIELDS_NUMBERING, cppu::UnoType::get(), 0}, + /* Stampit It disable the print cancel button of the shown progress dialog. */ + { OUString("AllowPrintJobCancel"), HANDLE_ALLOW_PRINTJOB_CANCEL, cppu::UnoType::get(), 0}, + { OUString("UseFormerLineSpacing"), HANDLE_USE_FORMER_LINE_SPACING, cppu::UnoType::get(), 0}, + { OUString("AddParaSpacingToTableCells"), HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS, cppu::UnoType::get(), 0}, + { OUString("AddParaLineSpacingToTableCells"), HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, cppu::UnoType::get(), 0}, + { OUString("UseFormerObjectPositioning"), HANDLE_USE_FORMER_OBJECT_POSITIONING, cppu::UnoType::get(), 0}, + { OUString("UseFormerTextWrapping"), HANDLE_USE_FORMER_TEXT_WRAPPING, cppu::UnoType::get(), 0}, + { OUString("RedlineProtectionKey"), HANDLE_CHANGES_PASSWORD, cppu::UnoType< cppu::UnoSequenceType >::get(), 0}, + { OUString("ConsiderTextWrapOnObjPos"), HANDLE_CONSIDER_WRAP_ON_OBJPOS, cppu::UnoType::get(), 0}, + { OUString("IgnoreFirstLineIndentInNumbering"), HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, cppu::UnoType::get(), 0}, + { OUString("DoNotJustifyLinesWithManualBreak"), HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, cppu::UnoType::get(), 0}, + { OUString("DoNotResetParaAttrsForNumFont"), HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, cppu::UnoType::get(), 0}, + { OUString("TableRowKeep"), HANDLE_TABLE_ROW_KEEP, cppu::UnoType::get(), 0}, + { OUString("IgnoreTabsAndBlanksForLineCalculation"), HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, cppu::UnoType::get(), 0}, + { OUString("LoadReadonly"), HANDLE_LOAD_READONLY, cppu::UnoType::get(), 0}, + { OUString("DoNotCaptureDrawObjsOnPage"), HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, cppu::UnoType::get(), 0}, + { OUString("ClipAsCharacterAnchoredWriterFlyFrames"), HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES, cppu::UnoType::get(), 0}, + { OUString("UnxForceZeroExtLeading"), HANDLE_UNIX_FORCE_ZERO_EXT_LEADING, cppu::UnoType::get(), 0}, + { OUString("UseOldPrinterMetrics"), HANDLE_USE_OLD_PRINTER_METRICS, cppu::UnoType::get(), 0}, + { OUString("TabsRelativeToIndent"), HANDLE_TABS_RELATIVE_TO_INDENT, cppu::UnoType::get(), 0}, + { OUString("Rsid"), HANDLE_RSID, cppu::UnoType::get(), 0}, + { OUString("RsidRoot"), HANDLE_RSID_ROOT, cppu::UnoType::get(), 0}, + { OUString("ProtectForm"), HANDLE_PROTECT_FORM, cppu::UnoType::get(), 0}, + { OUString("MsWordCompTrailingBlanks"), HANDLE_MS_WORD_COMP_TRAILING_BLANKS, cppu::UnoType::get(), 0 }, + { OUString("MsWordCompMinLineHeightByFly"), HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, cppu::UnoType::get(), 0 }, + { OUString("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, cppu::UnoType::get(), 0}, + { OUString("ModifyPasswordInfo"), HANDLE_MODIFYPASSWORDINFO, cppu::UnoType< cppu::UnoSequenceType >::get(), 0}, + { OUString("MathBaselineAlignment"), HANDLE_MATH_BASELINE_ALIGNMENT, cppu::UnoType::get(), 0}, + { OUString("InvertBorderSpacing"), HANDLE_INVERT_BORDER_SPACING, cppu::UnoType::get(), 0}, + { OUString("CollapseEmptyCellPara"), HANDLE_COLLAPSE_EMPTY_CELL_PARA, cppu::UnoType::get(), 0}, + { OUString("SmallCapsPercentage66"), HANDLE_SMALL_CAPS_PERCENTAGE_66, cppu::UnoType::get(), 0}, + { OUString("TabOverflow"), HANDLE_TAB_OVERFLOW, cppu::UnoType::get(), 0}, + { OUString("UnbreakableNumberings"), HANDLE_UNBREAKABLE_NUMBERINGS, cppu::UnoType::get(), 0}, + { OUString("StylesNoDefault"), HANDLE_STYLES_NODEFAULT, cppu::UnoType::get(), 0}, + { OUString("FloattableNomargins"), HANDLE_FLOATTABLE_NOMARGINS, cppu::UnoType::get(), 0}, + { OUString("ClippedPictures"), HANDLE_CLIPPED_PICTURES, cppu::UnoType::get(), 0}, + { OUString("BackgroundParaOverDrawings"), HANDLE_BACKGROUND_PARA_OVER_DRAWINGS, cppu::UnoType::get(), 0}, + { OUString("EmbedFonts"), HANDLE_EMBED_FONTS, cppu::UnoType::get(), 0}, + { OUString("EmbedOnlyUsedFonts"), HANDLE_EMBED_USED_FONTS, cppu::UnoType::get(), 0}, + { OUString("EmbedLatinScriptFonts"), HANDLE_EMBED_LATIN_SCRIPT_FONTS, cppu::UnoType::get(), 0}, + { OUString("EmbedAsianScriptFonts"), HANDLE_EMBED_ASIAN_SCRIPT_FONTS, cppu::UnoType::get(), 0}, + { OUString("EmbedComplexScriptFonts"), HANDLE_EMBED_COMPLEX_SCRIPT_FONTS, cppu::UnoType::get(), 0}, + { OUString("EmbedSystemFonts"), HANDLE_EMBED_SYSTEM_FONTS, cppu::UnoType::get(), 0}, + { OUString("TabOverMargin"), HANDLE_TAB_OVER_MARGIN, cppu::UnoType::get(), 0}, + { OUString("TreatSingleColumnBreakAsPageBreak"), HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, cppu::UnoType::get(), 0}, + { OUString("SurroundTextWrapSmall"), HANDLE_SURROUND_TEXT_WRAP_SMALL, cppu::UnoType::get(), 0}, + { OUString("ApplyParagraphMarkFormatToNumbering"), HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, cppu::UnoType::get(), 0}, + { OUString("PropLineSpacingShrinksFirstLine"), HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE, cppu::UnoType::get(), 0}, + { OUString("SubtractFlysAnchoredAtFlys"), HANDLE_SUBTRACT_FLYS, cppu::UnoType::get(), 0}, + { OUString("DisableOffPagePositioning"), HANDLE_DISABLE_OFF_PAGE_POSITIONING, cppu::UnoType::get(), 0}, + { OUString("EmptyDbFieldHidesPara"), HANDLE_EMPTY_DB_FIELD_HIDES_PARA, cppu::UnoType::get(), 0 }, + { OUString("ContinuousEndnotes"), HANDLE_CONTINUOUS_ENDNOTES, cppu::UnoType::get(), 0 }, + { OUString("ProtectBookmarks"), HANDLE_PROTECT_BOOKMARKS, cppu::UnoType::get(), 0 }, + { OUString("ProtectFields"), HANDLE_PROTECT_FIELDS, cppu::UnoType::get(), 0 }, + { OUString("HeaderSpacingBelowLastPara"), HANDLE_HEADER_SPACING_BELOW_LAST_PARA, cppu::UnoType::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::get(), 0, 0}, + { OUString("IsSnapToGrid"), HANDLE_IS_SNAP_TO_GRID, cppu::UnoType::get(), 0, 0}, + { OUString("IsSynchroniseAxes"), HANDLE_IS_SYNCHRONISE_AXES, cppu::UnoType::get(), 0, 0}, + { OUString("HorizontalGridResolution"), HANDLE_HORIZONTAL_GRID_RESOLUTION, cppu::UnoType::get(), 0, 0}, + { OUString("HorizontalGridSubdivision"), HANDLE_HORIZONTAL_GRID_SUBDIVISION, cppu::UnoType::get(), 0, 0}, + { OUString("VerticalGridResolution"), HANDLE_VERTICAL_GRID_RESOLUTION, cppu::UnoType::get(), 0, 0}, + { OUString("VerticalGridSubdivision"), HANDLE_VERTICAL_GRID_SUBDIVISION, cppu::UnoType::get(), 0, 0}, + + { OUString("ShowParagraphEnd"), HANDLE_SHOW_PARAGRAPH_END, cppu::UnoType::get(), 0, 0}, + { OUString("ShowOptionalHyphens"), HANDLE_SHOW_OPTIONAL_HYPHENS, cppu::UnoType::get(), 0, 0}, + { OUString("ShowSpaces"), HANDLE_SHOW_SPACES, cppu::UnoType::get(), 0, 0}, + { OUString("ShowTabs"), HANDLE_SHOW_TABS, cppu::UnoType::get(), 0, 0}, + { OUString("ShowBreaks"), HANDLE_SHOW_BREAKS, cppu::UnoType::get(), 0, 0}, + { OUString("ShowHiddenText"), HANDLE_SHOW_HIDDEN_TEXT, cppu::UnoType::get(), 0, 0}, + { OUString("ShowHiddenParagraphs"), HANDLE_SHOW_HIDDEN_PARAGRAPHS, cppu::UnoType::get(), 0, 0}, + + { OUString("ShowTextLimitGuide"), HANDLE_SHOW_TEXT_LIMIT_GUIDE, cppu::UnoType::get(), 0, 0}, + { OUString("ShowTableLimitGuide"), HANDLE_SHOW_TABLE_LIMIT_GUIDE, cppu::UnoType::get(), 0, 0}, + { OUString("ShowSectionLimitGuide"), HANDLE_SHOW_SECTION_LIMIT_GUIDE, cppu::UnoType::get(), 0, 0}, + { OUString("ShowGuidesWhileMoving"), HANDLE_SHOW_GUIDES_WHILE_MOVING, cppu::UnoType::get(), 0, 0}, +*/ + { OUString(), 0, css::uno::Type(), 0} + }; + return new MasterPropertySetInfo ( aWriterSettingsInfoMap ); +} + +SwXDocumentSettings::SwXDocumentSettings ( SwXTextDocument * pModel ) +: MasterPropertySet ( lcl_createSettingsInfo (), + &Application::GetSolarMutex () ) +, mpModel ( pModel ) +, mpDocSh ( nullptr ) +, mpDoc ( nullptr ) +, mpPrinter( nullptr ) +, mbPreferPrinterPapersize( false ) +{ + registerSlave ( new SwXPrintSettings ( SwXPrintSettingsType::Document, mpModel->GetDocShell()->GetDoc() ) ); +} + +SwXDocumentSettings::~SwXDocumentSettings() + throw() +{ +} + +Any SAL_CALL SwXDocumentSettings::queryInterface( const Type& rType ) +{ + return ::cppu::queryInterface(rType, + // OWeakObject interfaces + &dynamic_cast(dynamic_cast(*this)), + &dynamic_cast(*this), + // my own interfaces + &dynamic_cast(*this), + &dynamic_cast(*this), + &dynamic_cast(*this), + &dynamic_cast(*this), + &dynamic_cast(*this)); +} +void SwXDocumentSettings::acquire () + throw () +{ + OWeakObject::acquire(); +} +void SwXDocumentSettings::release () + throw () +{ + OWeakObject::release(); +} + +uno::Sequence< uno::Type > SAL_CALL SwXDocumentSettings::getTypes( ) +{ + static const uno::Sequence< uno::Type > aTypes { + // from MasterPropertySet + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + }; + return aTypes; +} + +uno::Sequence< sal_Int8 > SAL_CALL SwXDocumentSettings::getImplementationId( ) +{ + return css::uno::Sequence(); +} + +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, static_cast < cppu::OWeakObject * > ( nullptr ) ); + + 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(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(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(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 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 ); + static sal_uInt16 const nRange[] = + { + FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER, + SID_HTML_MODE, SID_HTML_MODE, + SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, + SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, + 0 + }; + auto pItemSet = std::make_unique( mpDoc->GetAttrPool(), nRange ); + VclPtr 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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION, bIsKern); + SwEditShell* pEditSh = mpDoc->GetEditShell(); + if(pEditSh) + pEditSh->ChgHyphenation(); + } + break; + case HANDLE_CHARACTER_COMPRESSION_TYPE: + { + sal_Int16 nMode = 0; + rValue >>= nMode; + switch (static_cast(nMode)) + { + case CharCompressType::NONE: + case CharCompressType::PunctuationOnly: + case CharCompressType::PunctuationAndKana: + break; + default: + throw IllegalArgumentException(); + } + mpDoc->getIDocumentSettingAccess().setCharacterCompressionType(static_cast(nMode)); + } + break; + case HANDLE_APPLY_USER_DATA: + { + mpDocSh->SetUseUserData(*o3tl::doAccess(rValue)); + } + break; + case HANDLE_SAVE_THUMBNAIL: + { + mpDocSh->SetUseThumbnailSave(*o3tl::doAccess(rValue)); + } + break; + case HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS: + { + bool bSaveGlobal = *o3tl::doAccess(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 + OUString sEmbeddedName; + if (rValue >>= sEmbeddedName) + mpDoc->GetDBManager()->setEmbeddedName(sEmbeddedName, *mpDocSh); +#endif + } + break; + case HANDLE_SAVE_VERSION_ON_CLOSE: + { + mpDocSh->SetSaveVersionOnClose( *o3tl::doAccess(rValue) ); + } + break; + case HANDLE_UPDATE_FROM_TEMPLATE: + { + mpDocSh->SetQueryLoadTemplate( *o3tl::doAccess(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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_FLY_OFFSETS, bTmp); + } + break; + case HANDLE_IS_ADD_VERTICAL_FLY_OFFSET: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS, bTmp); + } + break; + case HANDLE_IS_ADD_EXTERNAL_LEADING: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_EXT_LEADING, bTmp); + } + break; + case HANDLE_OLD_NUMBERING: + { + bool bTmp = *o3tl::doAccess(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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::OLD_LINE_SPACING, bTmp); + } + break; + case HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS: + { + bool bTmp = *o3tl::doAccess(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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, bTmp); + } + break; + case HANDLE_USE_FORMER_OBJECT_POSITIONING: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_OBJECT_POS, bTmp); + } + break; + case HANDLE_USE_FORMER_TEXT_WRAPPING: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING, bTmp); + } + break; + case HANDLE_CHANGES_PASSWORD: + { + Sequence 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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION, bTmp ); + } + break; + case HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: + { + bool bTmp = *o3tl::doAccess(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(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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, bTmp); + } + break; + case HANDLE_TABLE_ROW_KEEP: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TABLE_ROW_KEEP, bTmp); + } + break; + case HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, bTmp); + } + break; + case HANDLE_LOAD_READONLY: + { + mpDocSh->SetLoadReadonly( *o3tl::doAccess(rValue) ); + } + break; + case HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: + { + bool bTmp = *o3tl::doAccess(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(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(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(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(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FORM, bTmp); + } + break; + case HANDLE_MS_WORD_COMP_TRAILING_BLANKS: + { + bool bTmp = *o3tl::doAccess(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(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(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 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(rValue); + mpDoc->getIDocumentSettingAccess().set( DocumentSettingId::MATH_BASELINE_ALIGNMENT, bTmp ); + } + break; + case HANDLE_INVERT_BORDER_SPACING: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::INVERT_BORDER_SPACING, bTmp); + } + break; + case HANDLE_COLLAPSE_EMPTY_CELL_PARA: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA, bTmp); + } + break; + case HANDLE_SMALL_CAPS_PERCENTAGE_66: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SMALL_CAPS_PERCENTAGE_66, bTmp); + } + break; + case HANDLE_TAB_OVERFLOW: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVERFLOW, bTmp); + } + break; + case HANDLE_UNBREAKABLE_NUMBERINGS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::UNBREAKABLE_NUMBERINGS, bTmp); + } + break; + case HANDLE_STYLES_NODEFAULT: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::STYLES_NODEFAULT, bTmp); + } + break; + case HANDLE_FLOATTABLE_NOMARGINS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::FLOATTABLE_NOMARGINS, bTmp); + } + break; + case HANDLE_CLIPPED_PICTURES: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CLIPPED_PICTURES, bTmp); + } + break; + case HANDLE_BACKGROUND_PARA_OVER_DRAWINGS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS, bTmp); + } + break; + case HANDLE_EMBED_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_FONTS, bTmp); + } + break; + case HANDLE_EMBED_USED_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_USED_FONTS, bTmp); + } + break; + case HANDLE_EMBED_LATIN_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_LATIN_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_ASIAN_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_ASIAN_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_COMPLEX_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_COMPLEX_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_SYSTEM_FONTS: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_SYSTEM_FONTS, bTmp); + } + break; + case HANDLE_TAB_OVER_MARGIN: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_MARGIN, bTmp); + } + break; + case HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, bTmp); + } + break; + case HANDLE_SURROUND_TEXT_WRAP_SMALL: + { + bool bTmp = *o3tl::doAccess(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SURROUND_TEXT_WRAP_SMALL, bTmp); + } + break; + case HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING: + { + bool bTmp = *o3tl::doAccess(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; + 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: + { + Reference xRet(*mpModel->GetPropertyHelper(), UNO_QUERY); + rValue <<= xRet; + } + 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->GetDBDesc(); + rValue <<= rData.sDataSource; + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND: + { + const SwDBData& rData = mpDoc->GetDBDesc(); + rValue <<= rData.sCommand; + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND_TYPE: + { + const SwDBData& rData = mpDoc->GetDBDesc(); + rValue <<= rData.nCommandType; + } + break; + case HANDLE_EMBEDDED_DATABASE_NAME: + { +#if HAVE_FEATURE_DBCONNECTIVITY + 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_FLOATTABLE_NOMARGINS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::FLOATTABLE_NOMARGINS ); + } + 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_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; + 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 000000000..10ef572cb --- /dev/null +++ b/sw/source/uibase/uno/SwXDocumentSettings.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_UNO_SWXDOCUMENTSETTINGS_HXX +#define INCLUDED_SW_SOURCE_UIBASE_UNO_SWXDOCUMENTSETTINGS_HXX + +#include +#include +#include +#include +#include + +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 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() + throw() override; +public: + SwXDocumentSettings( SwXTextDocument* pModel ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire( ) + throw () override; + virtual void SAL_CALL release( ) + throw () 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; +}; +#endif + +/* 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 000000000..b36472bf5 --- /dev/null +++ b/sw/source/uibase/uno/SwXFilterOptions.cxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; + +#define FILTER_OPTIONS_NAME "FilterOptions" + +SwXFilterOptions::SwXFilterOptions() +{ +} + +SwXFilterOptions::~SwXFilterOptions() +{ +} + +uno::Sequence< beans::PropertyValue > SwXFilterOptions::getPropertyValues() +{ + return comphelper::InitPropertySequence({ + { FILTER_OPTIONS_NAME, uno::Any(sFilterOptions) } + }); +} + +void SwXFilterOptions::setPropertyValues( const uno::Sequence& aProps ) +{ + for (const beans::PropertyValue& rProp : aProps) + { + OUString aPropName = rProp.Name; + + if ( aPropName == FILTER_OPTIONS_NAME ) + rProp.Value >>= sFilterOptions; + else if ( aPropName == "InputStream" ) + rProp.Value >>= xInputStream; + } +} + +void SwXFilterOptions::setTitle( const OUString& /*rTitle*/ ) +{ +} + +sal_Int16 SwXFilterOptions::execute() +{ + sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL; + + std::unique_ptr pInStream; + if ( xInputStream.is() ) + pInStream = utl::UcbStreamHelper::CreateStream( xInputStream ); + + SwDocShell* pDocShell = nullptr; + if (auto pXDoc = comphelper::getUnoTunnelImplementation(xModel); pXDoc) + pDocShell = pXDoc->GetDocShell(); + + if(pDocShell) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pAsciiDlg(pFact->CreateSwAsciiFilterDlg(Application::GetFrameWeld(xDialogParent), *pDocShell, + pInStream.get())); + if(RET_OK == pAsciiDlg->Execute()) + { + SwAsciiOptions aOptions; + pAsciiDlg->FillOptions( aOptions ); + aOptions.WriteUserData(sFilterOptions); + nRet = ui::dialogs::ExecutableDialogResults::OK; + } + } + + return nRet; +} + +void SwXFilterOptions::setTargetDocument( const uno::Reference< XComponent >& xDoc ) +{ + xModel = xDoc; +} + +void SwXFilterOptions::setSourceDocument( const uno::Reference& xDoc ) +{ + xModel = xDoc; +} + +void SAL_CALL SwXFilterOptions::initialize(const uno::Sequence& rArguments) +{ + ::comphelper::NamedValueCollection aProperties(rArguments); + if (aProperties.has("ParentWindow")) + aProperties.get("ParentWindow") >>= 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 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 000000000..aeb72b540 --- /dev/null +++ b/sw/source/uibase/uno/dlelstnr.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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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 + { + xDesktop = frame::Desktop::create(xContext); + xDesktop->addTerminateListener( this ); + + xLngSvcMgr = LinguServiceManager::create(xContext); + xLngSvcMgr->addLinguServiceManagerListener( static_cast(this) ); + + if (SvtLinguConfig().HasGrammarChecker()) + { + xGCIterator = sw::proofreadingiterator::get(xContext); + Reference< XLinguServiceEventBroadcaster > xBC( xGCIterator, UNO_QUERY ); + if (xBC.is()) + xBC->addLinguServiceEventListener( static_cast(this) ); + } + } + catch (const uno::Exception&) + { + OSL_FAIL("exception caught in 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) + { + 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 (xLngSvcMgr.is() && rEventObj.Source == xLngSvcMgr) + xLngSvcMgr = nullptr; + if (xLngSvcMgr.is() && rEventObj.Source == xGCIterator) + xGCIterator = nullptr; +} + +void SAL_CALL SwLinguServiceEventListener::queryTermination( + const EventObject& /*rEventObj*/ ) +{ +} + +void SAL_CALL SwLinguServiceEventListener::notifyTermination( + const EventObject& rEventObj ) +{ + SolarMutexGuard aGuard; + + if (xDesktop.is() && rEventObj.Source == xDesktop) + { + if (xLngSvcMgr.is()) + xLngSvcMgr = nullptr; + if (xGCIterator.is()) + xGCIterator = nullptr; + xDesktop = nullptr; + } +} + +/* 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 000000000..2a13d735b --- /dev/null +++ b/sw/source/uibase/uno/unoatxt.cxx @@ -0,0 +1,1053 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +SwXAutoTextContainer::SwXAutoTextContainer() +{ + pGlossaries = ::GetGlossaries(); + +} + +SwXAutoTextContainer::~SwXAutoTextContainer() +{ + +} + +sal_Int32 SwXAutoTextContainer::getCount() +{ + OSL_ENSURE(pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32), + "SwXAutoTextContainer::getCount: too many items"); + return static_cast(pGlossaries->GetGroupCnt()); +} + +uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex) +{ + SolarMutexGuard aGuard; + const size_t nCount = pGlossaries->GetGroupCnt(); + if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount ) + throw lang::IndexOutOfBoundsException(); + return getByName(pGlossaries->GetGroupName( static_cast(nIndex) )); +} + +uno::Type SwXAutoTextContainer::getElementType() +{ + return cppu::UnoType::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 ( pGlossaries && hasByName( GroupName ) ) // group name already known? + // true = create group if not already available + xGroup = pGlossaries->GetAutoTextGroup( GroupName ); + + if ( !xGroup.is() ) + throw container::NoSuchElementException(); + + return makeAny( xGroup ); +} + +uno::Sequence< OUString > SwXAutoTextContainer::getElementNames() +{ + SolarMutexGuard aGuard; + const size_t nCount = pGlossaries->GetGroupCnt(); + OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32), + "SwXAutoTextContainer::getElementNames: too many groups"); + + uno::Sequence< OUString > aGroupNames(static_cast(nCount)); + OUString *pArr = aGroupNames.getArray(); + + for ( size_t i = 0; i < nCount; ++i ) + { + // The names will be passed without a path extension. + pArr[i] = 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( 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()) + { + lang::IllegalArgumentException aIllegal; + aIllegal.Message = "group name must not be empty"; + throw aIllegal; + } + 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; + } + lang::IllegalArgumentException aIllegal; + aIllegal.Message = "group name must contain a-z, A-z, '_', ' ' only"; + throw aIllegal; + } + OUString sGroup(aGroupName); + if (sGroup.indexOf(GLOS_DELIM)<0) + { + sGroup += OUStringChar(GLOS_DELIM) + "0"; + } + pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM)); + + uno::Reference< text::XAutoTextGroup > xGroup = 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 = pGlossaries->GetCompleteGroupName( aGroupName ); + if(sGroupName.isEmpty()) + throw container::NoSuchElementException(); + 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" }; +} + +namespace +{ + class theSwXAutoTextGroupUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXAutoTextGroupUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 > & SwXAutoTextGroup::getUnoTunnelId() +{ + return theSwXAutoTextGroupUnoTunnelId::get().getSeq(); +} + +sal_Int64 SAL_CALL SwXAutoTextGroup::getSomething( const uno::Sequence< sal_Int8 >& rId ) +{ + if( isUnoTunnelId(rId) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + } + return 0; +} + +SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName, + SwGlossaries* pGlos) : + pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)), + pGlossaries(pGlos), + 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 pGlosGroup(pGlossaries ? 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 pGlosGroup(pGlossaries ? 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* pInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange) +{ + OSL_ENSURE( pInsDoc, "no InsDoc"); + + SwNodes& rNds = pInsDoc->GetNodes(); + + SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 ); + SwContentNode * pNd = aIdx.GetNode().GetContentNode(); + SwPosition aPos(aIdx, SwIndex(pNd, pNd ? pNd->Len() : 0)); + + bool bRet = false; + pInsDoc->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; + } + + pInsDoc->getIDocumentFieldsAccess().UnlockExpFields(); + if( !pInsDoc->getIDocumentFieldsAccess().IsExpFieldsLocked() ) + pInsDoc->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 pGlosGroup; + if (pGlossaries) + pGlosGroup = pGlossaries->GetGroupDoc(m_sGroupName); + const OUString& sShortName(aName); + const OUString& sLongName(aTitle); + if (pGlosGroup && !pGlosGroup->GetError()) + { + uno::Reference xRangeTunnel( xTextRange, uno::UNO_QUERY); + SwXTextRange* pxRange = nullptr; + OTextCursorHelper* pxCursor = nullptr; + if(xRangeTunnel.is()) + { + pxRange = reinterpret_cast(xRangeTunnel->getSomething( + SwXTextRange::getUnoTunnelId())); + pxCursor = reinterpret_cast(xRangeTunnel->getSomething( + OTextCursorHelper::getUnoTunnelId())); + } + + 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 = pGlossaries ? + pGlossaries->GetAutoTextEntry( m_sGroupName, 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!", + static_cast < OWeakObject * > ( this ), + anyEx ); + } + + return xEntry; +} + +void SwXAutoTextGroup::removeByName(const OUString& aEntryName) +{ + SolarMutexGuard aGuard; + std::unique_ptr pGlosGroup(pGlossaries ? 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 sName; +} + +void SwXAutoTextGroup::setName(const OUString& rName) +{ + SolarMutexGuard aGuard; + if( !pGlossaries ) + throw uno::RuntimeException(); + + sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM ); + sal_Int32 nOldDelimPos = sName.lastIndexOf( GLOS_DELIM ); + + OUString aNewSuffix; + if (nNewDelimPos > -1) + aNewSuffix = rName.copy( nNewDelimPos + 1 ); + OUString aOldSuffix; + if (nOldDelimPos > -1) + aOldSuffix = 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) ? sName.copy( 0, nOldDelimPos ) : sName ); + + if ( 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 = pGlossaries; + + OUString sPreserveTitle( pGlossaries->GetGroupTitle( sName ) ); + if ( !pGlossaries->RenameGroupDoc( sName, sNewGroup, sPreserveTitle ) ) + throw uno::RuntimeException(); + sName = rName; + m_sGroupName = sNewGroup; + pGlossaries = pTempGlossaries; +} + +sal_Int32 SwXAutoTextGroup::getCount() +{ + SolarMutexGuard aGuard; + std::unique_ptr pGlosGroup(pGlossaries ? pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + return static_cast(pGlosGroup->GetCount()); +} + +uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex) +{ + SolarMutexGuard aGuard; + std::unique_ptr pGlosGroup(pGlossaries ? pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + const sal_uInt16 nCount = pGlosGroup->GetCount(); + if (nIndex < 0 || nIndex >= static_cast(nCount)) + throw lang::IndexOutOfBoundsException(); + return getByName(pGlosGroup->GetShortName(static_cast(nIndex))); +} + +uno::Type SwXAutoTextGroup::getElementType() +{ + return cppu::UnoType::get(); + +} + +sal_Bool SwXAutoTextGroup::hasElements() +{ + SolarMutexGuard aGuard; + std::unique_ptr pGlosGroup(pGlossaries ? 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 = pGlossaries->GetAutoTextEntry( m_sGroupName, sName, _rName ); + OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" ); + // we told it to create the object, so why didn't it? + return makeAny( xEntry ); +} + +uno::Sequence< OUString > SwXAutoTextGroup::getElementNames() +{ + SolarMutexGuard aGuard; + std::unique_ptr pGlosGroup(pGlossaries ? 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 pGlosGroup(pGlossaries ? 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 = pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXAutoTextGroup::setPropertyValue( + const OUString& rPropertyName, const uno::Any& aValue) +{ + SolarMutexGuard aGuard; + const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName ); + + if(!pEntry) + throw beans::UnknownPropertyException(rPropertyName); + + std::unique_ptr pGlosGroup(pGlossaries ? 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 SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); + + if(!pEntry) + throw beans::UnknownPropertyException(rPropertyName); + std::unique_ptr pGlosGroup(pGlossaries ? 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() +{ + pGlossaries = nullptr; + 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 aRet { "com.sun.star.text.AutoTextGroup" }; + return aRet; +} + +namespace +{ + class theSwXAutoTextEntryUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXAutoTextEntryUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 > & SwXAutoTextEntry::getUnoTunnelId() +{ + return theSwXAutoTextEntryUnoTunnelId::get().getSeq(); +} + +sal_Int64 SAL_CALL SwXAutoTextEntry::getSomething( const uno::Sequence< sal_Int8 >& rId ) +{ + if( isUnoTunnelId(rId) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + } + return 0; +} + +SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, const OUString& rGroupName, + const OUString& rEntryName) : + WeakComponentImplHelper(m_aMutex), + pGlossaries(pGlss), + sGroupName(rGroupName), + sEntryName(rEntryName) +{ +} + +SwXAutoTextEntry::~SwXAutoTextEntry() +{ + SolarMutexGuard aGuard; + + // ensure that any pending modifications are written + implFlushDocument( true ); +} + +void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc ) +{ + if ( xDocSh.is() ) + { + if ( xDocSh->GetDoc()->getIDocumentState().IsModified () ) + xDocSh->Save(); + + if ( _bCloseDoc ) + { + // stop listening at the document + EndListening( *xDocSh ); + + xDocSh->DoClose(); + xDocSh.clear(); + } + } +} + +void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) +{ + if ( &_rBC == xDocSh.get() ) + { // it's our document + if (const SfxEventHint* pEventHint = dynamic_cast(&_rHint)) + { + if (SfxEventHintId::PrepareCloseDoc == pEventHint->GetEventId()) + { + implFlushDocument(); + mxBodyText.clear(); + EndListening( *xDocSh ); + 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( *xDocSh ); + // and release our reference + xDocSh.clear(); + } + } + } +} + +void SwXAutoTextEntry::GetBodyText () +{ + SolarMutexGuard aGuard; + + xDocSh = pGlossaries->EditGroupDoc ( sGroupName, sEntryName, false ); + OSL_ENSURE( xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" ); + + // start listening at the document + StartListening( *xDocSh ); + + mxBodyText = new SwXBodyText ( xDocSh->GetDoc() ); +} + +void SwXAutoTextEntry::disposing() +{ + 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(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 + + uno::Reference xTunnel( xTextRange, uno::UNO_QUERY); + SwXTextRange* pRange = nullptr; + OTextCursorHelper* pCursor = nullptr; + SwXText *pText = nullptr; + + if(xTunnel.is()) + { + pRange = reinterpret_cast < SwXTextRange* > + ( xTunnel->getSomething( SwXTextRange::getUnoTunnelId() ) ); + pCursor = reinterpret_cast < OTextCursorHelper*> + ( xTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ) ); + pText = reinterpret_cast < SwXText* > + ( xTunnel->getSomething( SwXText::getUnoTunnelId() ) ); + } + + SwDoc* pDoc = nullptr; + if (pRange) + pDoc = &pRange->GetDoc(); + else if ( pCursor ) + pDoc = pCursor->GetDoc(); + else if ( pText && pText->GetDoc() ) + { + xTunnel.set(pText->getStart(), uno::UNO_QUERY); + if (xTunnel.is()) + { + pCursor = reinterpret_cast < OTextCursorHelper* > + ( xTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() ) ); + 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 pBlock(pGlossaries->GetGroupDoc(sGroupName)); + const bool bResult = pBlock && !pBlock->GetError() + && pDoc->InsertGlossary( *pBlock, 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 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), + rAutoTextEntry(rAutoText) +{ +} + +SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor() +{ +} + +OUString SwAutoTextEventDescriptor::getImplementationName() +{ + return "SwAutoTextEventDescriptor"; +} + +void SwAutoTextEventDescriptor::replaceByName( + const SvMacroItemId nEvent, + const SvxMacro& rMacro) +{ + OSL_ENSURE( nullptr != rAutoTextEntry.GetGlossaries(), + "Strangely enough, the AutoText vanished!" ); + OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) || + (nEvent == SvMacroItemId::SwStartInsGlossary) , + "Unknown event ID" ); + + SwGlossaries *const pGlossaries = + const_cast(rAutoTextEntry.GetGlossaries()); + std::unique_ptr pBlocks( + pGlossaries->GetGroupDoc( rAutoTextEntry.GetGroupName() )); + OSL_ENSURE( pBlocks, + "can't get autotext group; SwAutoTextEntry has illegal name?"); + + if( pBlocks && !pBlocks->GetError()) + { + sal_uInt16 nIndex = pBlocks->GetIndex( 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 != rAutoTextEntry.GetGlossaries(), "no AutoText" ); + OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) || + (nEvent == SvMacroItemId::SwStartInsGlossary) , + "Unknown event ID" ); + + SwGlossaries *const pGlossaries = + const_cast(rAutoTextEntry.GetGlossaries()); + std::unique_ptr pBlocks( + pGlossaries->GetGroupDoc( 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()) + { + sal_uInt16 nIndex = pBlocks->GetIndex( 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 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 000000000..6daaeee4e --- /dev/null +++ b/sw/source/uibase/uno/unodefaults.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 "unodefaults.hxx" +#include +#include +#include +#include + +SwSvxUnoDrawPool::SwSvxUnoDrawPool(SwDoc* pDoc) + : SvxUnoDrawPool(pDoc->getIDocumentDrawModelAccess().GetDrawModel(), SVXUNO_SERVICEID_COM_SUN_STAR_DRAWING_DEFAULTS_WRITER) + , m_pDoc(pDoc) +{ +} + +SwSvxUnoDrawPool::~SwSvxUnoDrawPool() throw() +{ +} + +SfxItemPool* SwSvxUnoDrawPool::getModelPool( bool /*bReadOnly*/ ) throw() +{ + if(m_pDoc) + { + + // DVO, OD 01.10.2003 #i18732# - return item pool of writer document; + // it contains draw model item pool as secondary pool. + //SdrModel* pModel = m_pDoc->MakeDrawModel(); + //return &pModel->GetItemPool(); + // #i52858# - method name changed + m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); + return &(m_pDoc->GetAttrPool()); + } + return nullptr; +} + +/* 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 000000000..23bd6b543 --- /dev/null +++ b/sw/source/uibase/uno/unodefaults.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_UNO_UNODEFAULTS_HXX +#define INCLUDED_SW_SOURCE_UIBASE_UNO_UNODEFAULTS_HXX + +#include + +class SwDoc; + +class SwSvxUnoDrawPool : public SvxUnoDrawPool +{ + SwDoc* m_pDoc; +public: + SwSvxUnoDrawPool(SwDoc* pDoc); + virtual ~SwSvxUnoDrawPool() throw() override; + + virtual SfxItemPool* getModelPool( bool bReadOnly ) throw() override; +}; + +#endif + +/* 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 000000000..77ef3e4a0 --- /dev/null +++ b/sw/source/uibase/uno/unodispatch.cxx @@ -0,0 +1,393 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +static const char cURLFormLetter[] = ".uno:DataSourceBrowser/FormLetter"; +static const char cURLInsertContent[] = ".uno:DataSourceBrowser/InsertContent";//data into fields +static const char cURLInsertColumns[] = ".uno:DataSourceBrowser/InsertColumns";//data into text +static const char cURLDocumentDataSource[] = ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document +static 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(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(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 SAL_CALL SwXDispatchProviderInterceptor::getInterceptedURLs() +{ + uno::Sequence 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.begin(), + [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference { + 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(this)); + uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->removeEventListener(static_cast(this)); + m_xDispatch = nullptr; + } + m_xIntercepted = nullptr; +} + +namespace +{ + class theSwXDispatchProviderInterceptorUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXDispatchProviderInterceptorUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 > & SwXDispatchProviderInterceptor::getUnoTunnelId() +{ + return theSwXDispatchProviderInterceptorUnoTunnelId::get().getSeq(); +} + +sal_Int64 SwXDispatchProviderInterceptor::getSomething( + const uno::Sequence< sal_Int8 >& aIdentifier ) +{ + if( isUnoTunnelId(aIdentifier) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + } + return 0; +} + +void SwXDispatchProviderInterceptor::Invalidate() +{ + DispatchMutexLock_Impl aLock; + if (m_xIntercepted.is()) + { + m_xIntercepted->releaseDispatchProviderInterceptor(static_cast(this)); + uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->removeEventListener(static_cast(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 xSupplier = m_pView->GetUNOObject(); + uno::Reference 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 + (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::makeAny(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 = *static_cast(this); + + const SwDBData& rData = m_pView->GetWrtShell().GetDBDesc(); + 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 = *static_cast(this); + aEvent.FeatureURL = aURL; + + // one of the URLs requires a special state... + if (aURL.Complete == cURLDocumentDataSource) + { + const SwDBData& rData = m_pView->GetWrtShell().GetDBDesc(); + + 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 xSupplier = m_pView->GetUNOObject(); + uno::Reference xThis = this; + xSupplier->addSelectionChangeListener(xThis); + m_bListenerAdded = true; + } +} + +void SwXDispatch::removeStatusListener( + const uno::Reference< frame::XStatusListener >& xControl, const util::URL& ) +{ + m_aStatusListenerVector.erase( + std::remove_if(m_aStatusListenerVector.begin(), m_aStatusListenerVector.end(), + [&](const StatusStruct_Impl& status) { return status.xListener.get() == xControl.get(); }), + m_aStatusListenerVector.end()); + if(m_aStatusListenerVector.empty() && m_pView) + { + uno::Reference xSupplier = m_pView->GetUNOObject(); + uno::Reference 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) + { + m_bOldEnable = bEnable; + frame::FeatureStateEvent aEvent; + aEvent.IsEnabled = bEnable; + aEvent.Source = *static_cast(this); + + // 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 xSupplier(rSource.Source, uno::UNO_QUERY); + uno::Reference xThis = this; + xSupplier->removeSelectionChangeListener(xThis); + m_bListenerAdded = false; + + lang::EventObject aObject; + aObject.Source = static_cast(this); + // 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 000000000..a61b23778 --- /dev/null +++ b/sw/source/uibase/uno/unodoc.cxx @@ -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 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +// com.sun.star.comp.Writer.TextDocument + +uno::Sequence< OUString > SwTextDocument_getSupportedServiceNames() throw() +{ + // return only top level services here! All others must be + // resolved by rtti! + uno::Sequence< OUString > aRet { "com.sun.star.text.TextDocument" }; + return aRet; +} + +OUString SwTextDocument_getImplementationName() throw() +{ + return "com.sun.star.comp.Writer.TextDocument"; +} + +uno::Reference< uno::XInterface > SwTextDocument_createInstance( + const uno::Reference< lang::XMultiServiceFactory >&, SfxModelFlags _nCreationFlags ) +{ + SolarMutexGuard aGuard; + SwGlobals::ensure(); + SfxObjectShell* pShell = new SwDocShell( _nCreationFlags ); + return uno::Reference< uno::XInterface >( pShell->GetModel() ); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_Writer_WebDocument_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence 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 const &) +{ + SolarMutexGuard aGuard; + SwGlobals::ensure(); + SfxObjectShell* pShell = new SwGlobalDocShell( SfxObjectCreateMode::STANDARD ); + uno::Reference< uno::XInterface > model( pShell->GetModel() ); + model->acquire(); + return model.get(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unofreg.cxx b/sw/source/uibase/uno/unofreg.cxx new file mode 100644 index 000000000..a170bb085 --- /dev/null +++ b/sw/source/uibase/uno/unofreg.cxx @@ -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 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; + +extern "C" +{ + +SAL_DLLPUBLIC_EXPORT void * sw_component_getFactory( + const char * pImplName, + void * pServiceManager, + void * ) +{ + void * pRet = nullptr; + if( pServiceManager ) + { + uno::Reference< XMultiServiceFactory > xMSF( + static_cast< XMultiServiceFactory * >( pServiceManager ) ); + + uno::Reference< XSingleServiceFactory > xFactory; + + const sal_Int32 nImplNameLen = strlen( pImplName ); + if( SwTextDocument_getImplementationName().equalsAsciiL( + pImplName, nImplNameLen ) ) + { + xFactory = ::sfx2::createSfxModelFactory( xMSF, + SwTextDocument_getImplementationName(), + SwTextDocument_createInstance, + SwTextDocument_getSupportedServiceNames() ); + } + + if( xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + return pRet; +} + +} // extern "C" + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +SwXMailMerge_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence const &) +{ +#if HAVE_FEATURE_DBCONNECTIVITY + 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 000000000..2e47a54e1 --- /dev/null +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -0,0 +1,1174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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( 1 ); + aArgs[0].Name = "Hidden"; + aArgs[0].Value <<= 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::getUnoTunnelImplementation(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 + { + 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, + const OUString& _rTemporaryFile ); + + 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, const OUString& _rTemporaryFile ) + : + m_xDocument( _rxModel, UNO_QUERY ) + ,m_sTemporaryFile( _rTemporaryFile ) + ,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&) + { + OSL_FAIL("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( 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, static_cast < cppu::OWeakObject * > ( this ) ); + 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, static_cast < cppu::OWeakObject * > ( this ) ); + } + 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, static_cast < cppu::OWeakObject * > ( this ), 0 ); + if (UCB_IsReadOnlyFileName(aCurOutputURL)) + throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, static_cast < cppu::OWeakObject * > ( this ), 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, static_cast < cppu::OWeakObject * > ( this ) ); + + if (!bOK) + throw IllegalArgumentException("Property type mismatch or property not set: " + rName, static_cast < cppu::OWeakObject * > ( this ), 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'.", + static_cast < cppu::OWeakObject * > ( this ), + 0 + ); + } + + aCurSelection = aTranslated; + } + + SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh.get(), false); + SwView *pView = pFrame ? dynamic_cast( pFrame->GetViewShell() ) : nullptr; + if (!pView) + throw RuntimeException(); + SwWrtShell &rSh = *pView->GetWrtShellPtr(); + + // 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.", static_cast < cppu::OWeakObject * > ( this ), 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", makeAny( xCurConnection ) ); + xRowSetPropSet->setPropertyValue( "DataSourceName", makeAny( aCurDataSourceName ) ); + xRowSetPropSet->setPropertyValue( "Command", makeAny( aCurDataCommand ) ); + xRowSetPropSet->setPropertyValue( "CommandType", makeAny( nCurDataCommandType ) ); + xRowSetPropSet->setPropertyValue( "EscapeProcessing", makeAny( bCurEscapeProcessing ) ); + xRowSetPropSet->setPropertyValue( "ApplyFilter", makeAny( true ) ); + xRowSetPropSet->setPropertyValue( "Filter", makeAny( 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", static_cast < cppu::OWeakObject * > ( this ), 0 ); + } + + 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.", static_cast < cppu::OWeakObject * > ( this ) ); + } + + aURLObj.SetSmartURL( aCurOutputURL ); + OUString aPath = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + + const OUString aDelim( "/" ); + 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.", static_cast < cppu::OWeakObject * > ( this ) ); + 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.", static_cast < cppu::OWeakObject * > ( this ) ); + } + break; + } + + // save document with temporary filename + std::shared_ptr pSfxFlt = SwIoSystem::GetFilterOfFormat( + FILTER_XML, + SwDocShell::Factory().GetFilterContainer() ); + OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*')); + utl::TempFile aTempFile( "SwMM", true, &aExtension ); + m_aTmpFileName = aTempFile.GetURL(); + + 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.", static_cast < cppu::OWeakObject * > ( this ) ); + + 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.", static_cast < cppu::OWeakObject * > ( this ) ); + + //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 makeAny( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell()->GetBaseModel() ); + } + else + return makeAny( 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(this)->m_aMergeListeners ); + while (aIt.hasMoreElements()) + { + Reference< XMailMergeListener > xRef( aIt.next(), UNO_QUERY ); + if (xRef.is()) + xRef->notifyMailMergeEvent( rEvt ); + } +} + +void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const +{ + cppu::OInterfaceContainerHelper *pContainer = + m_aPropListeners.getContainer( rEvt.PropertyHandle ); + if (pContainer) + { + cppu::OInterfaceIteratorHelper aIt( *pContainer ); + while (aIt.hasMoreElements()) + { + Reference< XPropertyChangeListener > xRef( aIt.next(), UNO_QUERY ); + if (xRef.is()) + xRef->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 SfxItemPropertySimpleEntry* 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, static_cast < cppu::OWeakObject * > ( this ) ); + 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, static_cast < cppu::OWeakObject * > ( this ), 0 ); + if (UCB_IsReadOnlyFileName(aText)) + throw IllegalArgumentException("URL is read-only: " + aText, static_cast < cppu::OWeakObject * > ( this ), 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, static_cast < cppu::OWeakObject * > ( this ), 0 ); + + if (bChanged) + { + PropertyChangeEvent aChgEvt( static_cast(this), rPropertyName, + false, pCur->nWID, aOld, rValue ); + launchEvent( aChgEvt ); + } + } +} + +uno::Any SAL_CALL SwXMailMerge::getPropertyValue( + const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + + Any aRet; + + const SfxItemPropertySimpleEntry* 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 SfxItemPropertySimpleEntry* 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 SfxItemPropertySimpleEntry* 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(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 000000000..48d84b512 --- /dev/null +++ b/sw/source/uibase/uno/unomod.cxx @@ -0,0 +1,970 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +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, +}; + +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 ChainablePropertySetInfo * lcl_createViewSettingsInfo() +{ + static PropertyInfo const aViewSettingsMap_Impl[] = + { + { OUString( "HelpURL" ), HANDLE_VIEWSET_HELP_URL , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "HorizontalRulerMetric"),HANDLE_VIEWSET_HORI_RULER_METRIC , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "IsRasterVisible"), HANDLE_VIEWSET_IS_RASTER_VISIBLE, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "IsSnapToRaster"), HANDLE_VIEWSET_IS_SNAP_TO_RASTER, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "IsVertRulerRightAligned"),HANDLE_VIEWSET_VRULER_RIGHT , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowContentTips" ), HANDLE_VIEWSET_SHOW_CONTENT_TIPS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowInlineTooltips" ), HANDLE_VIEWSET_INLINECHANGES_TIPS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "UseHeaderFooterMenu" ), HANDLE_VIEWSET_USE_HEADERFOOTERMENU , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "RasterResolutionX"), HANDLE_VIEWSET_RASTER_RESOLUTION_X, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "RasterResolutionY"), HANDLE_VIEWSET_RASTER_RESOLUTION_Y, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "RasterSubdivisionX"), HANDLE_VIEWSET_RASTER_SUBDIVISION_X, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "RasterSubdivisionY"), HANDLE_VIEWSET_RASTER_SUBDIVISION_Y, cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowAnnotations" ), HANDLE_VIEWSET_ANNOTATIONS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowBookmarks" ), HANDLE_VIEWSET_BOOKMARKS, cppu::UnoType::get(), PROPERTY_NONE }, + { OUString( "ShowBreaks"), HANDLE_VIEWSET_BREAKS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowDrawings"), HANDLE_VIEWSET_DRAWINGS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowFieldCommands"), HANDLE_VIEWSET_FIELD_COMMANDS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowFootnoteBackground"),HANDLE_VIEWSET_FOOTNOTE_BACKGROUND , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowGraphics"), HANDLE_VIEWSET_GRAPHICS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenCharacters"), HANDLE_VIEWSET_HIDDEN_CHARACTERS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "HideWhitespace"), HANDLE_VIEWSET_HIDE_WHITESPACE , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenParagraphs"), HANDLE_VIEWSET_HIDDEN_PARAGRAPHS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenText"), HANDLE_VIEWSET_HIDDEN_TEXT , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowHoriRuler"), HANDLE_VIEWSET_HRULER , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowHoriScrollBar"), HANDLE_VIEWSET_HSCROLL , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowIndexMarkBackground"),HANDLE_VIEWSET_INDEX_MARK_BACKGROUND, cppu::UnoType::get(),PROPERTY_NONE}, + { OUString( "ShowNonprintingCharacters"),HANDLE_VIEWSET_NONPRINTING_CHARACTERS, cppu::UnoType::get(),PROPERTY_NONE}, + { OUString( "ShowOnlineLayout"), HANDLE_VIEWSET_ONLINE_LAYOUT , cppu::UnoType::get(), PropertyAttribute::MAYBEVOID}, + { OUString( "ShowParaBreaks"), HANDLE_VIEWSET_PARA_BREAKS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowProtectedSpaces"), HANDLE_VIEWSET_PROTECTED_SPACES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowRulers"), HANDLE_VIEWSET_SHOW_RULER , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowScrollBarTips"), HANDLE_VIEWSET_SCROLLBAR_TIPS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowSoftHyphens"), HANDLE_VIEWSET_SOFT_HYPHENS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowSpaces"), HANDLE_VIEWSET_SPACES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowTableBoundaries"), HANDLE_VIEWSET_TABLE_BOUNDARIES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowTables"), HANDLE_VIEWSET_TABLES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowTabstops"), HANDLE_VIEWSET_TABSTOPS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowTextBoundaries"), HANDLE_VIEWSET_TEXT_BOUNDARIES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowTextFieldBackground"),HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND, cppu::UnoType::get(),PROPERTY_NONE}, + { OUString( "ShowVertRuler"), HANDLE_VIEWSET_VRULER , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ShowVertScrollBar"), HANDLE_VIEWSET_VSCROLL , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "SmoothScrolling"), HANDLE_VIEWSET_SMOOTH_SCROLLING , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "VerticalRulerMetric"), HANDLE_VIEWSET_VERT_RULER_METRIC , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ZoomType"), HANDLE_VIEWSET_ZOOM_TYPE , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "ZoomValue"), HANDLE_VIEWSET_ZOOM , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString(), 0, css::uno::Type(), 0 } + }; + return new ChainablePropertySetInfo ( aViewSettingsMap_Impl ); +} + +static ChainablePropertySetInfo * lcl_createPrintSettingsInfo() +{ + static PropertyInfo const aPrintSettingsMap_Impl[] = + { + { OUString( "PrintAnnotationMode" ), HANDLE_PRINTSET_ANNOTATION_MODE , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintBlackFonts" ), HANDLE_PRINTSET_BLACK_FONTS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintControls" ), HANDLE_PRINTSET_CONTROLS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintDrawings" ), HANDLE_PRINTSET_DRAWINGS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintGraphics" ), HANDLE_PRINTSET_GRAPHICS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintHiddenText"), HANDLE_PRINTSET_HIDDEN_TEXT , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintLeftPages" ), HANDLE_PRINTSET_LEFT_PAGES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintPageBackground" ), HANDLE_PRINTSET_PAGE_BACKGROUND , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintProspect" ), HANDLE_PRINTSET_PROSPECT , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintProspectRTL" ), HANDLE_PRINTSET_PROSPECT_RTL , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintReversed" ), HANDLE_PRINTSET_REVERSED , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintRightPages" ), HANDLE_PRINTSET_RIGHT_PAGES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintFaxName" ), HANDLE_PRINTSET_FAX_NAME , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintPaperFromSetup" ), HANDLE_PRINTSET_PAPER_FROM_SETUP , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintTables" ), HANDLE_PRINTSET_TABLES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintTextPlaceholder"), HANDLE_PRINTSET_PLACEHOLDER , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintSingleJobs" ), HANDLE_PRINTSET_SINGLE_JOBS , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString( "PrintEmptyPages" ), HANDLE_PRINTSET_EMPTY_PAGES , cppu::UnoType::get(), PROPERTY_NONE}, + { OUString(), 0, css::uno::Type(), 0} + }; + return new ChainablePropertySetInfo ( aPrintSettingsMap_Impl ); +} + +SwXModule::SwXModule() : + mxViewSettings(), + mxPrintSettings() +{ +} + +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 (), &Application::GetSolarMutex() ) +, meType(eType) +, mpPrtOpt ( nullptr ) +, mpDoc ( pDoc ) +{ +} + +SwXPrintSettings::~SwXPrintSettings() + throw() +{ +} + +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(const uno::Any &rValue) + { + const auto xPrSet = o3tl::tryAccess(rValue); + if (!xPrSet) + throw lang::IllegalArgumentException(); + return *xPrSet; + } +} + +void SwXPrintSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue ) +{ + switch( rInfo.mnHandle ) + { + case HANDLE_PRINTSET_LEFT_PAGES: + { + mpPrtOpt->SetPrintLeftPage(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_RIGHT_PAGES: + { + mpPrtOpt->SetPrintRightPage(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_REVERSED: + { + mpPrtOpt->SetPrintReverse(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_PROSPECT: + { + mpPrtOpt->SetPrintProspect(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_GRAPHICS: + { + mpPrtOpt->SetPrintGraphic(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_TABLES: + { + mpPrtOpt->SetPrintTable(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_DRAWINGS: + { + mpPrtOpt->SetPrintDraw(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_CONTROLS: + { + mpPrtOpt->SetPrintControl(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_PAGE_BACKGROUND: + { + mpPrtOpt->SetPrintPageBackground(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_BLACK_FONTS: + { + mpPrtOpt->SetPrintBlackFont(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_SINGLE_JOBS: + { + mpPrtOpt->SetPrintSingleJobs(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_PAPER_FROM_SETUP: + { + mpPrtOpt->SetPaperFromSetup(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_ANNOTATION_MODE: + { + sal_Int16 nTmp = 0; + rValue >>= nTmp; + SwPostItMode nVal = static_cast(nTmp); + if(nVal > SwPostItMode::EndPage) + throw lang::IllegalArgumentException(); + + mpPrtOpt->SetPrintPostIts(nVal); + } + break; + case HANDLE_PRINTSET_EMPTY_PAGES: + { + mpPrtOpt->SetPrintEmptyPages(tryBoolAccess(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(rValue)); + } + break; + case HANDLE_PRINTSET_PLACEHOLDER: + { + mpPrtOpt->SetPrintTextPlaceholder(tryBoolAccess(rValue)); + } + break; + case HANDLE_PRINTSET_HIDDEN_TEXT: + { + mpPrtOpt->SetPrintHiddenText(tryBoolAccess(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 aRet { "com.sun.star.text.PrintSettings" }; + return aRet; +} + +SwXViewSettings::SwXViewSettings(SwView* pVw) + : ChainablePropertySet( lcl_createViewSettingsInfo (), &Application::GetSolarMutex() ) + , pView(pVw) + , mpConstViewOption(nullptr) + , bObjectValid(true) + , mbApplyZoom(false) + , eHRulerUnit(FieldUnit::CM) + , mbApplyHRulerMetric(false) + , eVRulerUnit(FieldUnit::CM) + , mbApplyVRulerMetric(false) +{ + // This property only exists if we have a view (ie, not at the module ) + if ( !pView ) + mxInfo->remove ( "HelpURL" ); + +} + +SwXViewSettings::~SwXViewSettings() + throw() +{ + +} + +void SwXViewSettings::_preSetValues () +{ + const SwViewOption* pVOpt = nullptr; + if(pView) + { + if(!IsValid()) + return; + pVOpt = pView->GetWrtShell().GetViewOptions(); + } + else + pVOpt = SW_MOD()->GetViewOption(false); + + mpViewOption.reset( new SwViewOption (*pVOpt) ); + mbApplyZoom = false; + if(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(rValue)); break; + case HANDLE_VIEWSET_HRULER : mpViewOption->SetViewHRuler(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_VRULER : mpViewOption->SetViewVRuler(*o3tl::doAccess(rValue));break; + case HANDLE_VIEWSET_VRULER_RIGHT : mpViewOption->SetVRulerRight(*o3tl::doAccess(rValue));break; + case HANDLE_VIEWSET_HSCROLL : mpViewOption->SetViewHScrollBar(*o3tl::doAccess(rValue));break; + case HANDLE_VIEWSET_VSCROLL : mpViewOption->SetViewVScrollBar(*o3tl::doAccess(rValue));break; + case HANDLE_VIEWSET_GRAPHICS : mpViewOption->SetGraphic(*o3tl::doAccess(rValue));break; + case HANDLE_VIEWSET_TABLES : mpViewOption->SetTable(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_DRAWINGS : mpViewOption->SetDraw(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_FIELD_COMMANDS : mpViewOption->SetFieldName(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_ANNOTATIONS : mpViewOption->SetPostIts(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_INDEX_MARK_BACKGROUND : SwViewOption::SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess(rValue), true); break; + case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: mpViewOption->SetViewMetaChars( *o3tl::doAccess(rValue) ); break; + case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : SwViewOption::SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess(rValue), true); break; + case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : SwViewOption::SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess(rValue), true); break; + case HANDLE_VIEWSET_PARA_BREAKS : mpViewOption->SetParagraph(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_SOFT_HYPHENS : mpViewOption->SetSoftHyph(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_SPACES : mpViewOption->SetBlank(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_PROTECTED_SPACES : mpViewOption->SetHardBlank(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_TABSTOPS : mpViewOption->SetTab(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_BREAKS : mpViewOption->SetLineBreak(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_BOOKMARKS : mpViewOption->SetShowBookmarks(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_TEXT : mpViewOption->SetShowHiddenField(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_CHARACTERS : mpViewOption->SetShowHiddenChar(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_PARAGRAPHS : mpViewOption->SetShowHiddenPara(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_TABLE_BOUNDARIES : SwViewOption::SetAppearanceFlag(ViewOptFlags::TableBoundaries, *o3tl::doAccess(rValue), true); break; + case HANDLE_VIEWSET_TEXT_BOUNDARIES : SwViewOption::SetDocBoundaries(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_SMOOTH_SCROLLING : mpViewOption->SetSmoothScroll(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_SHOW_CONTENT_TIPS : mpViewOption->SetShowContentTips(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_IS_RASTER_VISIBLE : mpViewOption->SetGridVisible(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_IS_SNAP_TO_RASTER : mpViewOption->SetSnap(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_SCROLLBAR_TIPS : mpViewOption->SetShowScrollBarTips(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_INLINECHANGES_TIPS : mpViewOption->SetShowInlineTooltips(*o3tl::doAccess(rValue)); break; + case HANDLE_VIEWSET_USE_HEADERFOOTERMENU : mpViewOption->SetUseHeaderFooterMenu(*o3tl::doAccess(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( convertMm100ToTwip( nTmp ) ); + 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( convertMm100ToTwip( nTmp ) ); + 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(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(nTmp) ); + } + break; + case HANDLE_VIEWSET_ZOOM : + { + sal_Int16 nZoom = 0; + if(!(rValue >>= nZoom) || nZoom > MAXZOOM || nZoom < MINZOOM) + throw lang::IllegalArgumentException(); + mpViewOption->SetZoom(static_cast(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 ( pView ) + { + bool bVal = *o3tl::doAccess(rValue); + SwViewOption aOpt(*pView->GetWrtShell().GetViewOptions()); + if (!bVal != !aOpt.getBrowseMode()) + { + aOpt.setBrowseMode( bVal ); + pView->GetWrtShell().ApplyViewOptions( aOpt ); + + // must be set in mpViewOption as this will overwrite settings in _post! + if(mpViewOption) + mpViewOption->setBrowseMode(bVal); + + pView->GetDocShell()->ToggleLayoutMode(pView); + } + } + } + break; + case HANDLE_VIEWSET_HIDE_WHITESPACE: + { + if ( pView ) + { + bool bVal = *o3tl::doAccess(rValue); + SwViewOption aOpt(*pView->GetWrtShell().GetViewOptions()); + if (!bVal != !aOpt.IsHideWhitespaceMode()) + { + aOpt.SetHideWhitespaceMode( bVal ); + 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 ( !pView ) + throw UnknownPropertyException(); + + OUString sHelpURL; + if ( ! ( rValue >>= sHelpURL ) ) + throw IllegalArgumentException(); + + INetURLObject aHID( sHelpURL ); + if ( aHID.GetProtocol() != INetProtocol::Hid ) + throw IllegalArgumentException (); + + pView->GetEditWin().SetHelpId( OUStringToOString( aHID.GetURLPath(), RTL_TEXTENCODING_UTF8 ) ); + } + break; + case HANDLE_VIEWSET_HORI_RULER_METRIC: + case HANDLE_VIEWSET_VERT_RULER_METRIC: + { + sal_uInt16 nUnit; + if( rValue >>= nUnit ) + switch (static_cast(nUnit)) + { + case FieldUnit::MM: + case FieldUnit::CM: + case FieldUnit::POINT: + case FieldUnit::PICA: + case FieldUnit::INCH: + if( rInfo.mnHandle == HANDLE_VIEWSET_HORI_RULER_METRIC ) + { + eHRulerUnit = static_cast(nUnit); + mbApplyHRulerMetric = true; + } + else + { + eVRulerUnit = static_cast(nUnit); + mbApplyVRulerMetric = true; + } + break; + default: + throw IllegalArgumentException(); + } + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXViewSettings::_postSetValues() +{ + if( pView ) + { + if(mbApplyZoom ) + pView->SetZoom( mpViewOption->GetZoomType(), + mpViewOption->GetZoom(), true ); + if(mbApplyHRulerMetric) + pView->ChangeTabMetric(eHRulerUnit); + if(mbApplyVRulerMetric) + pView->ChangeVRulerMetric(eVRulerUnit); + + } + else + { + if(mbApplyHRulerMetric) + SW_MOD()->ApplyRulerMetric( eHRulerUnit, true, false ); + if(mbApplyVRulerMetric) + SW_MOD()->ApplyRulerMetric( eVRulerUnit, false, false ); + } + + SW_MOD()->ApplyUsrPref( *mpViewOption, pView, pView ? SvViewOpt::DestViewOnly + : SvViewOpt::DestText ); + + mpViewOption.reset(); +} + +void SwXViewSettings::_preGetValues () +{ + if(pView) + { + if(!IsValid()) + return; + mpConstViewOption = 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 = SwViewOption::IsFieldShadings(); break; + case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: bBoolVal = mpConstViewOption->IsViewMetaChars(); break; + case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : bBoolVal = SwViewOption::IsFieldShadings(); break; + case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : bBoolVal = SwViewOption::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 = SwViewOption::IsTableBoundaries(); break; + case HANDLE_VIEWSET_TEXT_BOUNDARIES : bBoolVal = SwViewOption::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_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(convertTwipToMm100(mpConstViewOption->GetSnapSize().Width())); + break; + case HANDLE_VIEWSET_RASTER_RESOLUTION_Y : + bBool = false; + rValue <<= static_cast(convertTwipToMm100(mpConstViewOption->GetSnapSize().Height())); + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_X : + bBool = false; + rValue <<= static_cast(mpConstViewOption->GetDivisionX()); + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_Y : + bBool = false; + rValue <<= static_cast(mpConstViewOption->GetDivisionY()); + break; + case HANDLE_VIEWSET_ZOOM : + bBool = false; + rValue <<= static_cast(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(pView) + bBoolVal = pView->GetWrtShell().GetViewOptions()->getBrowseMode(); + break; + case HANDLE_VIEWSET_HELP_URL : + { + if ( !pView ) + throw UnknownPropertyException(); + + bBool = false; + OUStringBuffer sHelpURL; + sHelpURL.append ( INET_HID_SCHEME ); + SwEditWin &rEditWin = pView->GetEditWin(); + sHelpURL.append( OUString::fromUtf8( rEditWin.GetHelpId() ) ); + rValue <<= sHelpURL.makeStringAndClear(); + } + break; + case HANDLE_VIEWSET_HORI_RULER_METRIC: + { + if ( pView ) + { + FieldUnit eUnit; + pView->GetHRulerMetric( eUnit ); + rValue <<= static_cast(eUnit); + } + else + { + const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false ); + rValue <<= static_cast(pUsrPref->GetHScrollMetric()); + } + bBool = false; + } + break; + case HANDLE_VIEWSET_VERT_RULER_METRIC: + { + if ( pView ) + { + FieldUnit eUnit; + pView->GetVRulerMetric( eUnit ); + rValue <<= static_cast(eUnit); + } + else + { + const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false ); + rValue <<= static_cast(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 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 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 000000000..0d595e773 --- /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 +#include + +#include +#include +#include "unomodule.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_Writer_WriterModule_get_implementation(uno::XComponentContext* /*pCtx*/, + uno::Sequence 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 xDesktop = css::frame::Desktop::create(::comphelper::getProcessComponentContext()); + css::uno::Reference 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 SfxPoolItem* pResult = SW_MOD()->ExecuteSlot( aReq ); + if ( pResult ) + 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.begin(), + [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.set(static_cast< frame::XDispatch* >(this), uno::UNO_QUERY); + + 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 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 000000000..1d2157eff --- /dev/null +++ b/sw/source/uibase/uno/unomodule.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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_UNO_UNOMODULE_HXX +#define INCLUDED_SW_SOURCE_UIBASE_UNO_UNOMODULE_HXX + +#include +#include +#include +#include +#include +#include + +#include + +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; +}; + +#endif + +/* 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 000000000..b65386a7c --- /dev/null +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -0,0 +1,4475 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "unodefaults.hxx" +#include "SwXDocumentSettings.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TWIPS_PER_PIXEL 15 + +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 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(pFrame->Lower()); + while (pPage && nMax-- > 0) + { + if (pPage->getFrameArea().Height() == 0) + nCurrentPage--; + pPage = static_cast(pPage->GetNext()); + } + } + return std::make_unique( nCurrentPage, bWebDoc, bSwSrcView, bHasSelection, bHasPostIts, rPrintData ); +} + +static SwTextFormatColl *lcl_GetParaStyle(const OUString& rCollName, SwDoc* pDoc) +{ + SwTextFormatColl* pColl = pDoc->FindTextFormatCollByName( rCollName ); + if( !pColl ) + { + const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( + rCollName, SwGetPoolIdFromName::TxtColl ); + if( USHRT_MAX != nId ) + pColl = pDoc->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 +{ +private: + ::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2 + +public: + ::comphelper::OInterfaceContainerHelper2 m_RefreshListeners; + + Impl() : m_RefreshListeners(m_Mutex) { } + +}; + +namespace +{ + class theSwXTextDocumentUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextDocumentUnoTunnelId > {}; +} + +const Sequence< sal_Int8 > & SwXTextDocument::getUnoTunnelId() +{ + return theSwXTextDocumentUnoTunnelId::get().getSeq(); +} + +sal_Int64 SAL_CALL SwXTextDocument::getSomething( const Sequence< sal_Int8 >& rId ) +{ + if( isUnoTunnelId(rId) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + } + if( isUnoTunnelId(rId) ) + { + return sal::static_int_cast(reinterpret_cast(pDocShell )); + } + + sal_Int64 nRet = SfxBaseModel::getSomething( rId ); + if (nRet) + return nRet; + + GetNumberFormatter(); + if (!xNumFormatAgg.is()) // may happen if not valid or no SwDoc + return 0; + Any aNumTunnel = xNumFormatAgg->queryAggregation(cppu::UnoType::get()); + Reference 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::get()) + { + Reference xTmp = this; + aRet <<= xTmp; + } + if ( !aRet.hasValue() && + rType == cppu::UnoType::get()) + { + Reference xTmp = this; + aRet <<= xTmp; + } + + if ( !aRet.hasValue() + && rType != cppu::UnoType::get() + && rType != cppu::UnoType::get() + && rType != cppu::UnoType::get() + && rType != cppu::UnoType::get() + && rType != cppu::UnoType::get() + && rType != cppu::UnoType::get()) + { + GetNumberFormatter(); + if(xNumFormatAgg.is()) + aRet = xNumFormatAgg->queryAggregation(rType); + } + return aRet; +} + +void SAL_CALL SwXTextDocument::acquire()throw() +{ + SfxBaseModel::acquire(); +} + +void SAL_CALL SwXTextDocument::release()throw() +{ + SfxBaseModel::release(); +} + +Reference< XAdapter > SwXTextDocument::queryAdapter( ) +{ + return SfxBaseModel::queryAdapter(); +} + +Sequence< uno::Type > SAL_CALL SwXTextDocument::getTypes() +{ + Sequence< uno::Type > aNumTypes; + GetNumberFormatter(); + if(xNumFormatAgg.is()) + { + const uno::Type& rProvType = cppu::UnoType::get(); + Any aNumProv = xNumFormatAgg->queryAggregation(rProvType); + Reference xNumProv; + if(aNumProv >>= xNumProv) + { + aNumTypes = xNumProv->getTypes(); + } + } + return comphelper::concatSequences( + SfxBaseModel::getTypes(), + SwXTextDocumentBaseClass::getTypes(), + aNumTypes, + Sequence { + cppu::UnoType::get(), + cppu::UnoType::get()}); +} + +SwXTextDocument::SwXTextDocument(SwDocShell* pShell) + : SfxBaseModel(pShell) + , m_pImpl(new Impl) + , + pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_DOCUMENT)), + + pDocShell(pShell), + + bObjectValid(pShell != nullptr), + + pDrawPage(nullptr), + mxXDrawPage(), + pBodyText(nullptr), + mxXNumberingRules(), + mxXFootnotes(), + mxXFootnoteSettings(), + mxXEndnotes(), + mxXEndnoteSettings(), + mxXReferenceMarks(), + mxXTextFieldTypes(), + mxXTextFieldMasters(), + mxXTextSections(), + mxXBookmarks(), + mxXTextTables(), + mxXTextFrames(), + mxXGraphicObjects(), + mxXEmbeddedObjects(), + mxXStyleFamilies(), + mxXAutoStyles(), + mxXChapterNumbering(), + mxXDocumentIndexes(), + + mxXLineNumberingProperties(), + mxLinkTargetSupplier(), + mxXRedlines(), + m_pHiddenViewFrame(nullptr), + // #i117783# + bApplyPagePrintSettingsFromXPagePrintable( false ) +{ +} + +SdrModel& SwXTextDocument::getSdrModelFromUnoModel() const +{ + OSL_ENSURE(pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(), "No SdrModel in SwDoc, should not happen"); + return *pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel(); +} + +SwXTextDocument::~SwXTextDocument() +{ + InitNewDoc(); + if(xNumFormatAgg.is()) + { + Reference< XInterface > x0; + xNumFormatAgg->setDelegator(x0); + 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(*pDocShell->GetDoc()); + } + return mxPropertyHelper.get(); +} + +void SwXTextDocument::GetNumberFormatter() +{ + if(IsValid()) + { + if(!xNumFormatAgg.is()) + { + if ( pDocShell->GetDoc() ) + { + SvNumberFormatsSupplierObj* pNumFormat = new SvNumberFormatsSupplierObj( + pDocShell->GetDoc()->GetNumberFormatter()); + Reference< util::XNumberFormatsSupplier > xTmp = pNumFormat; + xNumFormatAgg.set(xTmp, UNO_QUERY); + } + if(xNumFormatAgg.is()) + xNumFormatAgg->setDelegator(static_cast(static_cast(this))); + } + else + { + const uno::Type& rTunnelType = cppu::UnoType::get(); + Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); + SvNumberFormatsSupplierObj* pNumFormat = nullptr; + Reference< XUnoTunnel > xNumTunnel; + if(aNumTunnel >>= xNumTunnel) + { + pNumFormat = reinterpret_cast( + xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); + + } + OSL_ENSURE(pNumFormat, "No number formatter available"); + if (pNumFormat && !pNumFormat->GetNumberFormatter()) + pNumFormat->SetNumberFormatter(pDocShell->GetDoc()->GetNumberFormatter()); + } + } +} + +Reference< XText > SwXTextDocument::getText() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!xBodyText.is()) + { + pBodyText = new SwXBodyText(pDocShell->GetDoc()); + xBodyText = pBodyText; + } + return 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(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(SfxViewShell::GetFirst(true, checkSfxViewShell)); + while(pView && pView->GetObjectShell() != pDocShell) + { + pView = static_cast(SfxViewShell::GetNext(*pView, true, checkSfxViewShell)); + } + 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() +{ + SfxBaseModel::dispose(); +} + +void SwXTextDocument::close( sal_Bool bDeliverOwnership ) +{ + if(pDocShell) + { + uno::Sequence< uno::Any > aArgs; + pDocShell->CallAutomationDocumentEventSinks( "Close", aArgs ); + } + SolarMutexGuard aGuard; + if(IsValid() && m_pHiddenViewFrame) + lcl_DisposeView( m_pHiddenViewFrame, 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(pDocShell->GetDoc()); + } + return mxXLineNumberingProperties; +} + +Reference< XIndexReplace > SwXTextDocument::getChapterNumberingRules() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXChapterNumbering.is()) + { + mxXChapterNumbering = new SwXChapterNumbering(*pDocShell); + } + return mxXChapterNumbering; +} + +Reference< XIndexAccess > SwXTextDocument::getNumberingRules() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXNumberingRules.is() ) + { + mxXNumberingRules = new SwXNumberingRulesCollection( 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, 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(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, pDocShell->GetDoc()); + } + return mxXEndnotes; +} + +Reference< XPropertySet > SwXTextDocument::getEndnoteSettings() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXEndnoteSettings.is()) + { + mxXEndnoteSettings = new SwXEndnoteProperties(pDocShell->GetDoc()); + } + return mxXEndnoteSettings; +} + +Reference< util::XReplaceDescriptor > SwXTextDocument::createReplaceDescriptor() +{ + SolarMutexGuard aGuard; + Reference< util::XReplaceDescriptor > xRet = new SwXTextSearch; + return xRet; +} + +SwUnoCursor* SwXTextDocument::CreateCursorForSearch(Reference< XTextCursor > & xCursor) +{ + getText(); + XText *const pText = xBodyText.get(); + SwXBodyText* pBText = static_cast(pText); + SwXTextCursor *const pXTextCursor = pBText->CreateTextCursor(true); + xCursor.set( static_cast(pXTextCursor) ); + + auto& rUnoCursor(pXTextCursor->GetCursor()); + rUnoCursor.SetRemainInSection(false); + return &rUnoCursor; +} + +sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > & xDesc) +{ + SolarMutexGuard aGuard; + Reference< XUnoTunnel > xDescTunnel(xDesc, UNO_QUERY_THROW); + if(!IsValid() || !xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + Reference< XTextCursor > xCursor; + auto pUnoCursor(CreateCursorForSearch(xCursor)); + + const SwXTextSearch* pSearch = reinterpret_cast( + xDescTunnel->getSomething(SwXTextSearch::getUnoTunnelId())); + + 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_uInt32 nResult; + UnoActionContext aContext(pDocShell->GetDoc()); + //try attribute search first + if(pSearch->HasSearchAttributes()||pSearch->HasReplaceAttributes()) + { + SfxItemSet aSearch(pDocShell->GetDoc()->GetAttrPool(), + svl::Items{}); + SfxItemSet aReplace(pDocShell->GetDoc()->GetAttrPool(), + svl::Items{}); + pSearch->FillSearchItemSet(aSearch); + pSearch->FillReplaceItemSet(aReplace); + bool bCancel; + nResult = static_cast(pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, + eStart, eEnd, bCancel, + static_cast(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(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(eRanges), + true ); + } + return static_cast(nResult); + +} + +Reference< util::XSearchDescriptor > SwXTextDocument::createSearchDescriptor() +{ + SolarMutexGuard aGuard; + Reference< util::XSearchDescriptor > xRet = new SwXTextSearch; + return xRet; + +} + +// 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 = comphelper::getUnoTunnelImplementation(xDesc); + if(!IsValid() || !pSearch) + return nullptr; + + auto pUnoCursor(CreateCursorForSearch(xCursor)); + + bool bParentInExtra = false; + if(xLastResult.is()) + { + Reference xCursorTunnel( xLastResult, UNO_QUERY); + OTextCursorHelper* pPosCursor = nullptr; + if(xCursorTunnel.is()) + { + pPosCursor = reinterpret_cast(xCursorTunnel->getSomething( + OTextCursorHelper::getUnoTunnelId())); + } + SwPaM* pCursor = pPosCursor ? pPosCursor->GetPaM() : nullptr; + if(pCursor) + { + *pUnoCursor->GetPoint() = *pCursor->End(); + pUnoCursor->DeleteMark(); + } + else + { + SwXTextRange* pRange = nullptr; + if(xCursorTunnel.is()) + { + pRange = reinterpret_cast(xCursorTunnel->getSomething( + SwXTextRange::getUnoTunnelId())); + } + if(!pRange) + return nullptr; + pRange->GetPositions(*pUnoCursor); + if(pUnoCursor->HasMark()) + { + if(*pUnoCursor->GetPoint() < *pUnoCursor->GetMark()) + pUnoCursor->Exchange(); + pUnoCursor->DeleteMark(); + } + } + const SwNode& rRangeNode = pUnoCursor->GetNode(); + 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()) + { + SfxItemSet aSearch( + pDocShell->GetDoc()->GetAttrPool(), + svl::Items< + 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>{}); + pSearch->FillSearchItemSet(aSearch); + bool bCancel; + nResult = static_cast(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 = static_cast(pUnoCursor->FindFormat(*pSearchColl, + eStart, eEnd, bCancel, + eRanges, pReplaceColl )); + } + else + { + //todo/mba: assuming that notes should be omitted + bool bCancel; + nResult = static_cast(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(*pDocShell->GetDoc(), + *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(*pDocShell->GetDoc(), + *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 = pDocShell->GetDoc()->GetPreviewPrtData(); + if(pData) + aData = *pData; + Any aVal; + aVal <<= static_cast(aData.GetRow()); + pArray[0] = beans::PropertyValue("PageRows", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(aData.GetCol()); + pArray[1] = beans::PropertyValue("PageColumns", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(convertTwipToMm100(aData.GetLeftSpace())); + pArray[2] = beans::PropertyValue("LeftMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(convertTwipToMm100(aData.GetRightSpace())); + pArray[3] = beans::PropertyValue("RightMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(convertTwipToMm100(aData.GetTopSpace())); + pArray[4] = beans::PropertyValue("TopMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(convertTwipToMm100(aData.GetBottomSpace())); + pArray[5] = beans::PropertyValue("BottomMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(convertTwipToMm100(aData.GetHorzSpace())); + pArray[6] = beans::PropertyValue("HoriMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast(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(nVal); + } + + return nRet; +} + +static OUString lcl_CreateOutlineString( size_t nIndex, + const SwOutlineNodes& rOutlineNodes, const SwNumRule* pOutlRule) +{ + OUStringBuffer sEntry; + const SwTextNode * pTextNd = rOutlineNodes[ nIndex ]->GetTextNode(); + SwNumberTree::tNumberVector aNumVector = pTextNd->GetNumberVector(); + if( pOutlRule && pTextNd->GetNumRule()) + for( int nLevel = 0; + nLevel <= pTextNd->GetActualListLevel(); + nLevel++ ) + { + long nVal = aNumVector[nLevel]; + nVal ++; + nVal -= pOutlRule->Get(nLevel).GetStart(); + sEntry.append(OUString::number( nVal )); + sEntry.append("."); + } + sEntry.append( rOutlineNodes[ nIndex ]-> + GetTextNode()->GetExpandText(nullptr) ); + return sEntry.makeStringAndClear(); +} + +void SwXTextDocument::setPagePrintSettings(const Sequence< beans::PropertyValue >& aSettings) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwPagePreviewPrtData aData; + //if only a few properties are coming, then use the current settings + const SwPagePreviewPrtData* pData = pDocShell->GetDoc()->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(static_cast(nVal)); + } + else if(sName == "PageColumns") + { + if(!nVal || nVal > 0xff) + throw RuntimeException("Invalid value"); + aData.SetCol(static_cast(nVal)); + } + else if(sName == "LeftMargin") + { + aData.SetLeftSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "RightMargin") + { + aData.SetRightSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "TopMargin") + { + aData.SetTopSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "BottomMargin") + { + aData.SetBottomSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "HoriMargin") + { + aData.SetHorzSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "VertMargin") + { + aData.SetVertSpace(convertMm100ToTwip(nVal)); + } + else if(sName == "IsLandscape") + { + auto b = o3tl::tryAccess(rVal); + bException = !b; + if (b) + { + aData.SetLandscape(*b); + } + } + else + bException = true; + if(bException) + throw RuntimeException(); + } + pDocShell->GetDoc()->SetPreviewPrtData(&aData); + +} + +void SwXTextDocument::printPages(const Sequence< beans::PropertyValue >& xOptions) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SfxViewFrame* pFrame = SfxViewFrame::LoadHiddenDocument( *pDocShell, SfxInterfaceId(7) ); + SfxRequest aReq(FN_PRINT_PAGEPREVIEW, SfxCallMode::SYNCHRON, + pDocShell->GetDoc()->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::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(nCopies) ) ); + } + + // Collate-Property + else if ( rProp.Name == UNO_NAME_COLLATE ) + { + auto b = o3tl::tryAccess(rProp.Value); + if ( !b ) + throw IllegalArgumentException(); + aReq.AppendItem(SfxBoolItem( SID_PRINT_COLLATE, *b ) ); + + } + + // Sort-Property + else if ( rProp.Name == UNO_NAME_SORT ) + { + auto b = o3tl::tryAccess(rProp.Value); + if ( !b ) + 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# + 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(pDocShell->GetDoc()); + } + return mxXReferenceMarks; +} + +Reference< XEnumerationAccess > SwXTextDocument::getTextFields() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFieldTypes.is()) + { + mxXTextFieldTypes = new SwXTextFieldTypes(pDocShell->GetDoc()); + } + return mxXTextFieldTypes; +} + +Reference< XNameAccess > SwXTextDocument::getTextFieldMasters() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFieldMasters.is()) + { + mxXTextFieldMasters = new SwXTextFieldMasters(pDocShell->GetDoc()); + } + return mxXTextFieldMasters; +} + +Reference< XNameAccess > SwXTextDocument::getEmbeddedObjects() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXEmbeddedObjects.is()) + { + mxXEmbeddedObjects = new SwXTextEmbeddedObjects(pDocShell->GetDoc()); + } + return mxXEmbeddedObjects; +} + +Reference< XNameAccess > SwXTextDocument::getBookmarks() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXBookmarks.is()) + { + mxXBookmarks = new SwXBookmarks(pDocShell->GetDoc()); + } + return mxXBookmarks; +} + +Reference< XNameAccess > SwXTextDocument::getTextSections() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextSections.is()) + { + mxXTextSections = new SwXTextSections(pDocShell->GetDoc()); + } + return mxXTextSections; +} + +Reference< XNameAccess > SwXTextDocument::getTextTables() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextTables.is()) + { + mxXTextTables = new SwXTextTables(pDocShell->GetDoc()); + } + return mxXTextTables; +} + +Reference< XNameAccess > SwXTextDocument::getGraphicObjects() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXGraphicObjects.is()) + { + mxXGraphicObjects = new SwXTextGraphicObjects(pDocShell->GetDoc()); + } + return mxXGraphicObjects; +} + +Reference< XNameAccess > SwXTextDocument::getTextFrames() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFrames.is()) + { + mxXTextFrames = new SwXTextFrames(pDocShell->GetDoc()); + } + return mxXTextFrames; +} + +Reference< XNameAccess > SwXTextDocument::getStyleFamilies() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXStyleFamilies.is()) + { + mxXStyleFamilies = new SwXStyleFamilies(*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(*pDocShell); + } + return mxXAutoStyles; + +} + +Reference< drawing::XDrawPage > SwXTextDocument::getDrawPage() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXDrawPage.is()) + { + pDrawPage = new SwXDrawPage(pDocShell->GetDoc()); + mxXDrawPage = pDrawPage; + // Create a Reference to trigger the complete initialization of the + // object. Otherwise in some corner cases it would get initialized + // at ::InitNewDoc -> which would get called during + // close() or dispose() -> n#681746 + uno::Reference xTriggerInit( mxXDrawPage, uno::UNO_QUERY ); + } + return mxXDrawPage; +} + +namespace { + +class SwDrawPagesObj : public cppu::WeakImplHelper< + css::drawing::XDrawPages, + css::lang::XServiceInfo> +{ +private: + css::uno::Reference< css::drawing::XDrawPageSupplier > m_xDoc; +public: + SwDrawPagesObj(const css::uno::Reference< css::drawing::XDrawPageSupplier >& rxDoc) : m_xDoc(rxDoc) {} + + // 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 + { + SolarMutexGuard aGuard; + return cppu::UnoType::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 SAL_CALL SwXTextDocument::getDrawPages() +{ + SolarMutexGuard aGuard; + return new SwDrawPagesObj(this); +} + +void SwXTextDocument::Invalidate() +{ + bObjectValid = false; + if(xNumFormatAgg.is()) + { + const uno::Type& rTunnelType = cppu::UnoType::get(); + Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); + SvNumberFormatsSupplierObj* pNumFormat = nullptr; + Reference< XUnoTunnel > xNumTunnel; + if(aNumTunnel >>= xNumTunnel) + { + pNumFormat = reinterpret_cast( + xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); + pNumFormat->SetNumberFormatter(nullptr); + } + OSL_ENSURE(pNumFormat, "No number formatter available"); + } + InitNewDoc(); + pDocShell = nullptr; + lang::EventObject const ev(static_cast(*this)); + m_pImpl->m_RefreshListeners.disposeAndClear(ev); +} + +void SwXTextDocument::Reactivate(SwDocShell* pNewDocShell) +{ + if(pDocShell && pDocShell != pNewDocShell) + Invalidate(); + pDocShell = pNewDocShell; + 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(pTables)->Invalidate(); + mxXTextTables.clear(); + } + + if(mxXTextFrames.is()) + { + XNameAccess* pFrames = mxXTextFrames.get(); + static_cast(pFrames)->Invalidate(); + mxXTextFrames.clear(); + } + + if(mxXGraphicObjects.is()) + { + XNameAccess* pFrames = mxXGraphicObjects.get(); + static_cast(pFrames)->Invalidate(); + mxXGraphicObjects.clear(); + } + + if(mxXEmbeddedObjects.is()) + { + XNameAccess* pOLE = mxXEmbeddedObjects.get(); + static_cast(pOLE)->Invalidate(); + mxXEmbeddedObjects.clear(); + } + + if(xBodyText.is()) + { + xBodyText = nullptr; + pBodyText = nullptr; + } + + if(xNumFormatAgg.is()) + { + const uno::Type& rTunnelType = cppu::UnoType::get(); + Any aNumTunnel = xNumFormatAgg->queryAggregation(rTunnelType); + SvNumberFormatsSupplierObj* pNumFormat = nullptr; + Reference< XUnoTunnel > xNumTunnel; + if(aNumTunnel >>= xNumTunnel) + { + pNumFormat = reinterpret_cast( + xNumTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId())); + + } + OSL_ENSURE(pNumFormat, "No number formatter available"); + if (pNumFormat) + pNumFormat->SetNumberFormatter(nullptr); + } + + if(mxXTextFieldTypes.is()) + { + XEnumerationAccess* pT = mxXTextFieldTypes.get(); + static_cast(pT)->Invalidate(); + mxXTextFieldTypes.clear(); + } + + if(mxXTextFieldMasters.is()) + { + XNameAccess* pT = mxXTextFieldMasters.get(); + static_cast(pT)->Invalidate(); + mxXTextFieldMasters.clear(); + } + + if(mxXTextSections.is()) + { + XNameAccess* pSect = mxXTextSections.get(); + static_cast(pSect)->Invalidate(); + mxXTextSections.clear(); + } + + if(mxXDrawPage.is()) + { + // #i91798#, #i91895# + // dispose XDrawPage here. We are the owner and know that it is no longer in a valid condition. + uno::Reference xComp( mxXDrawPage, uno::UNO_QUERY ); + xComp->dispose(); + pDrawPage->InvalidateSwDoc(); + mxXDrawPage.clear(); + } + + if ( mxXNumberingRules.is() ) + { + XIndexAccess* pNum = mxXNumberingRules.get(); + static_cast(pNum)->Invalidate(); + mxXNumberingRules.clear(); + } + + if(mxXFootnotes.is()) + { + XIndexAccess* pFootnote = mxXFootnotes.get(); + static_cast(pFootnote)->Invalidate(); + mxXFootnotes.clear(); + } + + if(mxXEndnotes.is()) + { + XIndexAccess* pFootnote = mxXEndnotes.get(); + static_cast(pFootnote)->Invalidate(); + mxXEndnotes.clear(); + } + + if(mxXDocumentIndexes.is()) + { + XIndexAccess* pIdxs = mxXDocumentIndexes.get(); + static_cast(pIdxs)->Invalidate(); + mxXDocumentIndexes.clear(); + } + + if(mxXStyleFamilies.is()) + { + XNameAccess* pStyles = mxXStyleFamilies.get(); + static_cast(pStyles)->Invalidate(); + mxXStyleFamilies.clear(); + } + if(mxXAutoStyles.is()) + { + XNameAccess* pStyles = mxXAutoStyles.get(); + static_cast(pStyles)->Invalidate(); + mxXAutoStyles.clear(); + } + + if(mxXBookmarks.is()) + { + XNameAccess* pBm = mxXBookmarks.get(); + static_cast(pBm)->Invalidate(); + mxXBookmarks.clear(); + } + + if(mxXChapterNumbering.is()) + { + XIndexReplace* pCh = mxXChapterNumbering.get(); + static_cast(pCh)->Invalidate(); + mxXChapterNumbering.clear(); + } + + if(mxXFootnoteSettings.is()) + { + XPropertySet* pFntSet = mxXFootnoteSettings.get(); + static_cast(pFntSet)->Invalidate(); + mxXFootnoteSettings.clear(); + } + + if(mxXEndnoteSettings.is()) + { + XPropertySet* pEndSet = mxXEndnoteSettings.get(); + static_cast(pEndSet)->Invalidate(); + mxXEndnoteSettings.clear(); + } + + if(mxXLineNumberingProperties.is()) + { + XPropertySet* pLine = mxXLineNumberingProperties.get(); + static_cast(pLine)->Invalidate(); + mxXLineNumberingProperties.clear(); + } + if(mxXReferenceMarks.is()) + { + XNameAccess* pMarks = mxXReferenceMarks.get(); + static_cast(pMarks)->Invalidate(); + mxXReferenceMarks.clear(); + } + if(mxLinkTargetSupplier.is()) + { + XNameAccess* pAccess = mxLinkTargetSupplier.get(); + static_cast(pAccess)->Invalidate(); + mxLinkTargetSupplier.clear(); + } + if(mxXRedlines.is()) + { + XEnumerationAccess* pMarks = mxXRedlines.get(); + static_cast(pMarks)->Invalidate(); + mxXRedlines.clear(); + } + if(mxPropertyHelper.is()) + { + mxPropertyHelper->Invalidate(); + mxPropertyHelper.clear(); + } +} + +css::uno::Reference SwXTextDocument::create( + OUString const & rServiceName, + css::uno::Sequence 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, *pDocShell->GetDoc()); + } + 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(*new SwXDocumentSettings(this)); + } + if (rServiceName == "com.sun.star.document.ImportEmbeddedObjectResolver") + { + return static_cast( + new SvXMLEmbeddedObjectHelper( + *pDocShell, SvXMLEmbeddedObjectHelperMode::Read)); + } + if (rServiceName == "com.sun.star.text.DocumentSettings") + { + return Reference(*new SwXDocumentSettings(this)); + } + if (rServiceName == "com.sun.star.chart2.data.DataProvider") + { + return Reference( + dynamic_cast( + 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 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, pDocShell->GetDoc()); + } + if (rServiceName.startsWith("com.sun.star.drawing.")) + { + return *new SwXShape(xTmp, 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[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( pDocShell ) != nullptr + ? OUString("com.sun.star.comp.Writer.GlobalDocument") + : dynamic_cast( 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( pDocShell) != nullptr ); + bool bGlobalDoc = (dynamic_cast( 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(pDocShell->GetDoc()); + } + return mxXDocumentIndexes; +} + +Reference< XPropertySetInfo > SwXTextDocument::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXTextDocument::setPropertyValue(const OUString& rPropertyName, const Any& aValue) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertySimpleEntry* pEntry = 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", + static_cast< cppu::OWeakObject * >( + static_cast< SwXTextDocumentBaseClass * >(this))); + 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: + { + bool bSet = *o3tl::doAccess(aValue); + RedlineFlags eMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(); + if(WID_DOC_CHANGES_SHOW == pEntry->nWID) + { + eMode |= RedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); + if( !bSet ) + pDocShell->GetDoc()->GetDocumentRedlineManager().SetHideRedlines(true); + } + else if(WID_DOC_CHANGES_RECORD == pEntry->nWID) + { + eMode = bSet ? eMode|RedlineFlags::On : eMode&~RedlineFlags::On; + } + pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); + } + break; + case WID_DOC_CHANGES_PASSWORD: + { + Sequence aNew; + if(aValue >>= aNew) + { + SwDoc* pDoc = pDocShell->GetDoc(); + pDoc->getIDocumentRedlineAccess().SetRedlinePassword(aNew); + if(aNew.hasElements()) + { + RedlineFlags eMode = pDoc->getIDocumentRedlineAccess().GetRedlineFlags(); + eMode |= RedlineFlags::On; + pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); + } + } + } + break; + case WID_DOC_AUTO_MARK_URL : + { + OUString sURL; + aValue >>= sURL; + pDocShell->GetDoc()->SetTOIAutoMarkURL(sURL); + } + break; + case WID_DOC_HIDE_TIPS : + SW_MOD()->GetModuleConfig()->SetHideFieldTips(*o3tl::doAccess(aValue)); + break; + case WID_DOC_REDLINE_DISPLAY: + { + RedlineFlags eRedMode = pDocShell->GetDoc()->getIDocumentRedlineAccess().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(); + } + pDocShell->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags(eRedMode); + } + break; + case WID_DOC_TWO_DIGIT_YEAR: + { + sal_Int16 nYear = 0; + aValue >>= nYear; + SfxRequest aRequest ( SID_ATTR_YEAR2000, SfxCallMode::SLOT, pDocShell->GetDoc()->GetAttrPool()); + aRequest.AppendItem(SfxUInt16Item( SID_ATTR_YEAR2000, static_cast < sal_uInt16 > ( nYear ) ) ); + pDocShell->Execute ( aRequest ); + } + break; + case WID_DOC_AUTOMATIC_CONTROL_FOCUS: + { + SwDrawModel * pDrawDoc; + bool bAuto = *o3tl::doAccess(aValue); + + if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) + pDrawDoc->SetAutoControlFocus( bAuto ); + else if (bAuto) + { + // 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 + pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); + pDrawDoc->SetAutoControlFocus ( bAuto ); + } + } + break; + case WID_DOC_APPLY_FORM_DESIGN_MODE: + { + SwDrawModel * pDrawDoc; + bool bMode = *o3tl::doAccess(aValue); + + if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) + pDrawDoc->SetOpenInDesignMode( bMode ); + else if (!bMode) + { + // 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 + pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); + pDrawDoc->SetOpenInDesignMode ( bMode ); + } + } + break; + // #i42634# New property to set the bInReading + // flag at the document, used during binary import + case WID_DOC_LOCK_UPDATES : + { + SwDoc* pDoc = pDocShell->GetDoc(); + bool bBool (false); + if( aValue >>= bBool ) + { + pDoc->SetInReading( bBool ); + } + } + break; + case WID_DOC_WRITERFILTER: + { + SwDoc* pDoc = pDocShell->GetDoc(); + bool bBool = {}; + if (aValue >>= bBool) + { // HACK: writerfilter has to use API to set this :( + pDoc->SetInWriterfilterImport(bBool); + } + } + break; + case WID_DOC_BUILDID: + aValue >>= maBuildId; + break; + + case WID_DOC_DEFAULT_PAGE_MODE: + { + bool bDefaultPageMode( false ); + aValue >>= bDefaultPageMode; + pDocShell->GetDoc()->SetDefaultPageMode( bDefaultPageMode ); + } + break; + case WID_DOC_INTEROP_GRAB_BAG: + setGrabBagItem(aValue); + break; + + default: + { + const SfxPoolItem& rItem = pDocShell->GetDoc()->GetDefault(pEntry->nWID); + std::unique_ptr pNewItem(rItem.Clone()); + pNewItem->PutValue(aValue, pEntry->nMemberId); + pDocShell->GetDoc()->SetDefault(*pNewItem); + } + } +} + +Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap().getByName( rPropertyName); + + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + Any aAny; + switch(pEntry->nWID) + { + case WID_DOC_ISTEMPLATEID : + aAny <<= pDocShell->IsTemplate(); + break; + case WID_DOC_CHAR_COUNT : + case WID_DOC_PARA_COUNT : + case WID_DOC_WORD_COUNT : + { + const SwDocStat& rStat(pDocShell->GetDoc()->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 = pDocShell->GetDoc()->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: + { + SwDoc* pDoc = pDocShell->GetDoc(); + aAny <<= pDoc->getIDocumentRedlineAccess().GetRedlinePassword(); + } + break; + case WID_DOC_AUTO_MARK_URL : + aAny <<= pDocShell->GetDoc()->GetTOIAutoMarkURL(); + break; + case WID_DOC_HIDE_TIPS : + aAny <<= SW_MOD()->GetModuleConfig()->IsHideFieldTips(); + break; + case WID_DOC_REDLINE_DISPLAY: + { + RedlineFlags eRedMode = pDocShell->GetDoc()->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 xRet(static_cast(mxPropertyHelper.get()), UNO_QUERY); + aAny <<= xRet; + } + break; + case WID_DOC_TWO_DIGIT_YEAR: + { + aAny <<= static_cast < sal_Int16 > (pDocShell->GetDoc()->GetNumberFormatter ()->GetYear2000()); + } + break; + case WID_DOC_AUTOMATIC_CONTROL_FOCUS: + { + SwDrawModel * pDrawDoc; + bool bAuto; + if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) + bAuto = pDrawDoc->GetAutoControlFocus(); + else + bAuto = false; + aAny <<= bAuto; + } + break; + case WID_DOC_APPLY_FORM_DESIGN_MODE: + { + SwDrawModel * pDrawDoc; + bool bMode; + if ( nullptr != ( pDrawDoc = pDocShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel() ) ) + bMode = pDrawDoc->GetOpenInDesignMode(); + else + bMode = true; + aAny <<= bMode; + } + break; + case WID_DOC_BASIC_LIBRARIES: + aAny <<= pDocShell->GetBasicContainer(); + break; + case WID_DOC_DIALOG_LIBRARIES: + aAny <<= 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 <<= pDocShell->GetDoc()->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 = pDocShell->GetDoc()->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(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(*this)); + m_pImpl->m_RefreshListeners.notifyEach( + & util::XRefreshListener::refreshed, ev); +} + +void SwXTextDocument::refresh() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwViewShell *pViewShell = pDocShell->GetWrtShell(); + NotifyRefreshListeners(); + if(pViewShell) + pViewShell->CalcLayout(); +} + +void SAL_CALL SwXTextDocument::addRefreshListener( + const Reference & xListener) +{ + // no need to lock here as m_pImpl is const and container threadsafe + m_pImpl->m_RefreshListeners.addInterface(xListener); +} + +void SAL_CALL SwXTextDocument::removeRefreshListener( + const Reference & xListener) +{ + // no need to lock here as m_pImpl is const and container threadsafe + m_pImpl->m_RefreshListeners.removeInterface(xListener); +} + +void SwXTextDocument::updateLinks( ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwDoc* pDoc = pDocShell->GetDoc(); + sfx2::LinkManager& rLnkMan = pDoc->getIDocumentLinksAdministration().GetLinkManager(); + if( !rLnkMan.GetLinks().empty() ) + { + UnoActionContext aAction(pDoc); + 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 SfxItemPropertySimpleEntry* pEntry = 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.begin(), + [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 SfxItemPropertySimpleEntry* pEntry = 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 SfxItemPropertySimpleEntry* pEntry = 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 = comphelper::getUnoTunnelImplementation( xRenderDevice ); + 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 == pDocShell->GetModel()) + pDoc = 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( 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(&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( 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(*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( 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(m_pHiddenViewFrame->GetViewShell())->GetWrtShellPtr(); + } + else + pViewShell = static_cast(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() && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() ) + { + 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( 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???" ); + + 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( 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(); + + // TODO/mba: we really need a generic way to get the SwViewShell! + SwViewShell* pVwSh = nullptr; + SwView* pSwView = dynamic_cast( pView ); + if ( pSwView ) + pVwSh = pSwView->GetWrtShellPtr(); + else + pVwSh = static_cast(pView)->GetViewShell(); + + 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 PageSisze 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 + { + 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.realloc(3); + aRenderer[0].Name = "PageSize"; + aRenderer[0].Value <<= aPageSize; + aRenderer[1].Name = "PageIncludesNonprintableArea"; + aRenderer[1].Value <<= true; + aRenderer[2].Name = "PagePos"; + aRenderer[2].Value <<= aPagePos; + if (aPreferredPageSize.Width && aPreferredPageSize.Height) + { + ++nLen; + aRenderer.realloc( nLen ); + aRenderer[ nLen - 1 ].Name = "PreferredPageSize"; + aRenderer[ nLen - 1 ].Value <<= aPreferredPageSize; + } + if (nPrinterPaperTray >= 0) + { + ++nLen; + aRenderer.realloc( nLen ); + aRenderer[ nLen - 1 ].Name = "PrinterPaperTray"; + aRenderer[ nLen - 1 ].Value <<= nPrinterPaperTray; + } + } + + // #i117783# + if ( bApplyPagePrintSettingsFromXPagePrintable ) + { + const SwPagePreviewPrtData* pPagePrintSettings = + pDocShell->GetDoc()->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 ); + // put page print settings attribute into render data + const sal_Int32 nRow = pPagePrintSettings->GetRow(); + aRenderer[ nRenderDataIdxStart + 0 ].Name = "NUpRows"; + aRenderer[ nRenderDataIdxStart + 0 ].Value <<= std::max( nRow, 1); + const sal_Int32 nCol = pPagePrintSettings->GetCol(); + aRenderer[ nRenderDataIdxStart + 1 ].Name = "NUpColumns"; + aRenderer[ nRenderDataIdxStart + 1 ].Value <<= std::max( nCol, 1); + aRenderer[ nRenderDataIdxStart + 2 ].Name = "NUpPageMarginLeft"; + aRenderer[ nRenderDataIdxStart + 2 ].Value <<= pPagePrintSettings->GetLeftSpace(); + aRenderer[ nRenderDataIdxStart + 3 ].Name = "NUpPageMarginRight"; + aRenderer[ nRenderDataIdxStart + 3 ].Value <<= pPagePrintSettings->GetRightSpace(); + aRenderer[ nRenderDataIdxStart + 4 ].Name = "NUpPageMarginTop"; + aRenderer[ nRenderDataIdxStart + 4 ].Value <<= pPagePrintSettings->GetTopSpace(); + aRenderer[ nRenderDataIdxStart + 5 ].Name = "NUpPageMarginBottom"; + aRenderer[ nRenderDataIdxStart + 5 ].Value <<= pPagePrintSettings->GetBottomSpace(); + aRenderer[ nRenderDataIdxStart + 6 ].Name = "NUpHorizontalSpacing"; + aRenderer[ nRenderDataIdxStart + 6 ].Value <<= pPagePrintSettings->GetHorzSpace(); + aRenderer[ nRenderDataIdxStart + 7 ].Name = "NUpVerticalSpacing"; + aRenderer[ nRenderDataIdxStart + 7 ].Value <<= pPagePrintSettings->GetVertSpace(); + { + Printer* pPrinter = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrinter( false ); + if ( pPrinter ) + { + 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() ); + } + aRenderer[ nRenderDataIdxStart + 8 ].Name = "NUpPaperSize"; + aRenderer[ nRenderDataIdxStart + 8 ].Value <<= aNewPageSize; + } + } + } + + 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( 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, 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(); + + 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( 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(*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(pView); + if (pSwView) + pVwSh = pSwView->GetWrtShellPtr(); + else + pVwSh = static_cast(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 evaulated during painting. + + SwWrtShell* pWrtShell = pSwView ? pSwView->GetWrtShellPtr() : nullptr; + + SwPrintData const& rSwPrtOptions = + *m_pRenderData->GetSwPrtOptions(); + + 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, pDocShell ); + m_pHiddenViewFrame = nullptr; + + // prevent crash described in #i108805 + SwDocShell *pRenderDocShell = pDoc->GetDocShell(); + SfxItemSet *pSet = pRenderDocShell->GetMedium()->GetItemSet(); + pSet->Put( SfxBoolItem( SID_HIDDEN, false ) ); + + } + } + } + } + } + } + if( bLastPage ) + { + m_pRenderData.reset(); + m_pPrintUIOptions.reset(); + } +} + +// xforms::XFormsSupplier +Reference SAL_CALL SwXTextDocument::getXForms() +{ + SolarMutexGuard aGuard; + if ( !pDocShell ) + throw DisposedException( OUString(), static_cast< XTextDocument* >( this ) ); + SwDoc* pDoc = pDocShell->GetDoc(); + return pDoc->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(this)); + } + + return SwUnoCursorHelper::CreateFlatParagraphIterator( + *pDocShell->GetDoc(), 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 = pDocShell->GetDoc()->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& xListener) +{ + SolarMutexGuard aGuard; + + if (IsValid() && xListener.is()) + pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener); +} + +void SwXTextDocument::removePasteEventListener( + const uno::Reference& xListener) +{ + SolarMutexGuard aGuard; + + if (IsValid() && xListener.is()) + pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener); +} + +void SwXTextDocument::paintTile( VirtualDevice &rDevice, + int nOutputWidth, int nOutputHeight, + int nTilePosX, int nTilePosY, + long nTileWidth, long nTileHeight ) +{ + SwViewShell* pViewShell = pDocShell->GetWrtShell(); + pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight, + nTilePosX, nTilePosY, nTileWidth, nTileHeight); + + LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight, + nTilePosX, nTilePosY, nTileWidth, nTileHeight); +} + +Size SwXTextDocument::getDocumentSize() +{ + SwViewShell* pViewShell = pDocShell->GetWrtShell(); + Size aDocSize = pViewShell->GetDocSize(); + + return Size(aDocSize.Width() + 2 * DOCUMENTBORDER, + aDocSize.Height() + 2 * DOCUMENTBORDER); +} + +void SwXTextDocument::setPart(int nPart) +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + if (!pWrtShell) + return; + + pWrtShell->GotoPage(nPart + 1, true); +} + +int SwXTextDocument::getParts() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + if (!pWrtShell) + return 0; + + return pWrtShell->GetPageCnt(); +} + +OUString SwXTextDocument::getPartPageRectangles() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + if (!pWrtShell) + return OUString(); + + return pWrtShell->getPageRectangles(); +} + +void SwXTextDocument::setClipboard(const uno::Reference& xClipboard) +{ + SolarMutexGuard aGuard; + + SwView* pView = pDocShell->GetView(); + if (pView) + pView->GetEditWin().SetClipboard(xClipboard); +} + +bool SwXTextDocument::isMimeTypeSupported() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = 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 = pDocShell->GetView()) + { + // set the PgUp/PgDown offset + pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3); + } + + if (SwViewShell* pViewShell = 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 = pDocShell->GetView()->GetIPClient(); + if (pIPClient) + { + SwViewShell* pWrtViewShell = pDocShell->GetWrtShell(); + double fScale = nTilePixelWidth_ * TWIPS_PER_PIXEL / (nTileTwipWidth_ * 1.0); + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + if (aOption.GetZoom() != fScale * 100) + { + aOption.SetZoom(fScale * 100); + 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 = pDocShell->GetWrtShell(); + if (!pWrtShell) + return PointerStyle::Arrow; + + return pWrtShell->GetView().GetEditWin().GetPointer(); +} + +OUString SwXTextDocument::getTrackedChanges() +{ + boost::property_tree::ptree aTrackedChanges; + + // Disable since usability is very low beyond some small number of changes. + static bool bDisableRedlineComments = getenv("DISABLE_REDLINE") != nullptr; + if (!bDisableRedlineComments) + { + const SwRedlineTable& rRedlineTable + = pDocShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i) + { + boost::property_tree::ptree aTrackedChange; + aTrackedChange.put("index", rRedlineTable[i]->GetId()); + aTrackedChange.put("author", rRedlineTable[i]->GetAuthorString(1).toUtf8().getStr()); + aTrackedChange.put("type", SwRedlineTypeToOUString( + rRedlineTable[i]->GetRedlineData().GetType()) + .toUtf8() + .getStr()); + aTrackedChange.put("comment", + rRedlineTable[i]->GetRedlineData().GetComment().toUtf8().getStr()); + aTrackedChange.put("description", rRedlineTable[i]->GetDescr().toUtf8().getStr()); + OUString sDateTime = utl::toISO8601( + rRedlineTable[i]->GetRedlineData().GetTimeStamp().GetUNODateTime()); + aTrackedChange.put("dateTime", sDateTime.toUtf8().getStr()); + + SwContentNode* pContentNd = rRedlineTable[i]->GetContentNode(); + SwView* pView = dynamic_cast(SfxViewShell::Current()); + if (pView && pContentNd) + { + SwShellCursor aCursor(pView->GetWrtShell(), *(rRedlineTable[i]->Start())); + aCursor.SetMark(); + aCursor.GetMark()->nNode = *pContentNd; + aCursor.GetMark()->nContent.Assign(pContentNd, + rRedlineTable[i]->End()->nContent.GetIndex()); + + aCursor.FillRects(); + + SwRects* pRects(&aCursor); + std::vector aRects; + for (const SwRect& rNextRect : *pRects) + aRects.push_back(rNextRect.SVRect().toString()); + + const OString sRects = comphelper::string::join("; ", aRects); + aTrackedChange.put("textRange", sRects.getStr()); + } + + aTrackedChanges.push_back(std::make_pair("", aTrackedChange)); + } + } + + boost::property_tree::ptree aTree; + aTree.add_child("redlines", aTrackedChanges); + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTree); + + return OUString::fromUtf8(aStream.str().c_str()); +} + +OUString SwXTextDocument::getTrackedChangeAuthors() +{ + return SW_MOD()->GetRedlineAuthorInfo(); +} + +OUString SwXTextDocument::getRulerState() +{ + SwView* pView = pDocShell->GetView(); + return OUString::fromUtf8(dynamic_cast(pView->GetHRuler()).CreateJsonNotification().c_str()); +} + +OUString SwXTextDocument::getPostIts() +{ + SolarMutexGuard aGuard; + boost::property_tree::ptree aAnnotations; + for (auto const& sidebarItem : *pDocShell->GetView()->GetPostItMgr()) + { + sw::annotation::SwAnnotationWin* pWin = sidebarItem->pPostIt.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 (!sidebarItem->maLayoutInfo.mPositionFromCommentAnchor) + { + // Comments on frames: anchor position is the corner position, not the whole frame. + aSVRect.SetSize(Size(0, 0)); + } + + std::vector 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); + + boost::property_tree::ptree aAnnotation; + aAnnotation.put("id", pField->GetPostItId()); + aAnnotation.put("parent", pWin->CalcParent()); + 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()); + + aAnnotations.push_back(std::make_pair("", aAnnotation)); + } + + boost::property_tree::ptree aTree; + aTree.add_child("comments", aAnnotations); + std::stringstream aStream; + boost::property_tree::write_json(aStream, aTree); + + return OUString::fromUtf8(aStream.str().c_str()); +} + +void SwXTextDocument::executeFromFieldEvent(const StringMap& aArguments) +{ + auto aIter = aArguments.find("type"); + if (aIter != aArguments.end() && aIter->second == "drop-down") + { + aIter = aArguments.find("cmd"); + if (aIter != aArguments.end() && aIter->second == "selected") + { + aIter = aArguments.find("data"); + if (aIter != aArguments.end()) + { + sal_Int32 nSelection = aIter->second.toInt32(); + SwPosition aPos(*pDocShell->GetWrtShell()->GetCursor()->GetPoint()); + sw::mark::IFieldmark* pFieldBM = pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getFieldmarkFor(aPos); + if ( !pFieldBM ) + { + --aPos.nContent; + pFieldBM = pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getFieldmarkFor(aPos); + } + if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN) + { + if (nSelection >= 0) + { + OUString sKey = ODF_FORMDROPDOWN_RESULT; + (*pFieldBM->GetParameters())[sKey] <<= nSelection; + pFieldBM->Invalidate(); + pDocShell->GetWrtShell()->SetModified(); + pDocShell->GetView()->GetEditWin().LogicInvalidate(nullptr); + } + } + } + } + } +} + +int SwXTextDocument::getPart() +{ + SolarMutexGuard aGuard; + + SwView* pView = pDocShell->GetView(); + if (!pView) + return 0; + + return pView->getPart(); +} + +OUString SwXTextDocument::getPartName(int nPart) +{ + SolarMutexGuard aGuard; + + return SwResId(STR_PAGE) + OUString::number(nPart + 1); +} + +OUString SwXTextDocument::getPartHash(int nPart) +{ + SolarMutexGuard aGuard; + OUString sPart(SwResId(STR_PAGE) + OUString::number(nPart + 1)); + + return OUString::number(sPart.hashCode()); +} + +VclPtr SwXTextDocument::getDocWindow() +{ + SolarMutexGuard aGuard; + VclPtr pWindow; + SwView* pView = pDocShell->GetView(); + if (pView) + pWindow = &(pView->GetEditWin()); + + LokChartHelper aChartHelper(pView); + VclPtr pChartWindow = aChartHelper.GetWindow(); + if (pChartWindow) + pWindow = pChartWindow; + + return pWindow; +} + +void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence& rArguments) +{ + SolarMutexGuard aGuard; + + SwViewShell* pViewShell = pDocShell->GetWrtShell(); + + SwView* pView = pDocShell->GetView(); + if (!pView) + return; + + pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true); + + // Tiled rendering defaults. + SwViewOption aViewOption(*pViewShell->GetViewOptions()); + aViewOption.SetHardBlank(false); + for (const beans::PropertyValue& rValue : rArguments) + { + if (rValue.Name == ".uno:HideWhitespace" && rValue.Value.has()) + aViewOption.SetHideWhitespaceMode(rValue.Value.get()); + else if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has()) + SwViewOption::SetAppearanceFlag(ViewOptFlags::Shadow , rValue.Value.get()); + else if (rValue.Name == ".uno:Author" && rValue.Value.has()) + { + // Store the author name in the view. + pView->SetRedlineAuthor(rValue.Value.get()); + // Let the actual author name pick up the value from the current + // view, which would normally happen only during the next view + // switch. + pDocShell->SetView(pView); + } + } + + // 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 = 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 + SvtSaveOptions().SetWarnAlienFormat(false); + + // 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 = pDocShell->GetWrtShell(); + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0); + + // check if the user hit a chart which is being edited by this view + SfxViewShell* pViewShell = pDocShell->GetView(); + LokChartHelper aChartHelper(pViewShell); + if (aChartHelper.postMouseEvent(nType, nX, nY, + nCount, nButtons, nModifier, + fScale, fScale)) + return; + + // check if the user hit a chart which is being edited by someone else + // and, if so, skip current mouse event + if (nType != LOK_MOUSEEVENT_MOUSEMOVE) + { + if (LokChartHelper::HitAny(Point(nX, nY))) + return; + } + + SwEditWin& rEditWin = pDocShell->GetView()->GetEditWin(); + 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 = pDocShell->GetView(); + LokChartHelper aChartHelper(pViewShell); + if (aChartHelper.setTextSelection(nType, nX, nY)) + return; + + SwEditWin& rEditWin = 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 SwXTextDocument::getSelection() +{ + SolarMutexGuard aGuard; + + uno::Reference xTransferable; + + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + if (SdrView* pSdrView = pWrtShell->GetDrawView()) + { + if (pSdrView->GetTextEditObject()) + { + // Editing shape text + EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); + xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection()); + } + } + + if (SwPostItMgr* pPostItMgr = 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()) + xTransferable = new SwTransferable(*pWrtShell); + + return xTransferable; +} + +void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY) +{ + SolarMutexGuard aGuard; + + SwViewShell* pWrtViewShell = pDocShell->GetWrtShell(); + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + double fScale = aOption.GetZoom() / (TWIPS_PER_PIXEL * 100.0); + + SfxViewShell* pViewShell = pDocShell->GetView(); + LokChartHelper aChartHelper(pViewShell); + if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale)) + return; + + SwEditWin& rEditWin = 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 = 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(nWindowHandle); + ScopedVclPtrInstance xDevice(aData, Size(1, 1), DeviceFormat::DEFAULT); + 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 (!pDocShell) + throw DisposedException(); + SwDoc* pDoc = pDocShell->GetDoc(); + + // avoid duplicate values + std::set< LanguageType > aAllLangs; + + //USER STYLES + + const SwCharFormats *pFormats = pDoc->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 = pDoc->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 > rStyles; + pDoc->GetIStyleAccess().getAllStyles(rStyles, i); + while (!rStyles.empty()) + { + std::shared_ptr pStyle = rStyles.back(); + rStyles.pop_back(); + const SfxItemSet *pSet = dynamic_cast< const SfxItemSet * >(pStyle.get()); + + LanguageType nLang = LANGUAGE_DONTKNOW; + if (bLatin) + { + assert(pSet); + nLang = dynamic_cast< const SvxLanguageItem & >(pSet->Get( RES_CHRATR_LANGUAGE, false )).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + assert(pSet); + nLang = dynamic_cast< const SvxLanguageItem & >(pSet->Get( RES_CHRATR_CJK_LANGUAGE, false )).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + assert(pSet); + nLang = dynamic_cast< const SvxLanguageItem & >(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 = pDocShell->GetWrtShell(); + SdrView *pSdrView = pWrtSh->GetDrawView(); + + if( pSdrView ) + { + SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner(); + if(pOutliner) + { + EditEngine& rEditEng = const_cast(pOutliner->GetEditEngine()); + sal_Int32 nParCount = pOutliner->GetParagraphCount(); + for (sal_Int32 nPar=0; nPar 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 = dynamic_cast< const SvxLanguageItem & >(aAttr.Get( EE_CHAR_LANGUAGE, false )).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + nLang = dynamic_cast< const SvxLanguageItem & >(aAttr.Get( EE_CHAR_LANGUAGE_CJK, false )).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + nLang = dynamic_cast< const SvxLanguageItem & >(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) : + pxDoc(&rxDoc) +{ + sTables = SwResId(STR_CONTENT_TYPE_TABLE); + sFrames = SwResId(STR_CONTENT_TYPE_FRAME); + sGraphics = SwResId(STR_CONTENT_TYPE_GRAPHIC); + sOLEs = SwResId(STR_CONTENT_TYPE_OLE); + sSections = SwResId(STR_CONTENT_TYPE_REGION); + sOutlines = SwResId(STR_CONTENT_TYPE_OUTLINE); + sBookmarks = SwResId(STR_CONTENT_TYPE_BOOKMARK); +} + +SwXLinkTargetSupplier::~SwXLinkTargetSupplier() +{ +} + +Any SwXLinkTargetSupplier::getByName(const OUString& rName) +{ + Any aRet; + if(!pxDoc) + throw RuntimeException("No document available"); + OUString sSuffix("|"); + if(rName == sTables) + { + sSuffix += "table"; + + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + pxDoc->getTextTables(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sFrames) + { + sSuffix += "frame"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + pxDoc->getTextFrames(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sSections) + { + sSuffix += "region"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + pxDoc->getTextSections(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sGraphics) + { + sSuffix += "graphic"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + pxDoc->getGraphicObjects(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sOLEs) + { + sSuffix += "ole"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + pxDoc->getEmbeddedObjects(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sOutlines) + { + sSuffix += "outline"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + *pxDoc, rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == sBookmarks) + { + sSuffix.clear(); + Reference< XNameAccess > xBkms = new SwXLinkNameAccessWrapper( + pxDoc->getBookmarks(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xBkms, UNO_QUERY); + } + else + throw NoSuchElementException(); + return aRet; +} + +Sequence< OUString > SwXLinkTargetSupplier::getElementNames() +{ + return { sTables, + sFrames, + sGraphics, + sOLEs, + sSections, + sOutlines, + sBookmarks }; +} + +sal_Bool SwXLinkTargetSupplier::hasByName(const OUString& rName) +{ + if( rName == sTables || + rName == sFrames || + rName == sGraphics|| + rName == sOLEs || + rName == sSections || + rName == sOutlines || + rName == sBookmarks ) + return true; + return false; +} + +uno::Type SwXLinkTargetSupplier::getElementType() +{ + return cppu::UnoType::get(); + +} + +sal_Bool SwXLinkTargetSupplier::hasElements() +{ + return nullptr != 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, const OUString& rLinkDisplayName, const OUString& sSuffix ) : + xRealAccess(xAccess), + pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + sLinkSuffix(sSuffix), + sLinkDisplayName(rLinkDisplayName), + pxDoc(nullptr) +{ +} + +SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(SwXTextDocument& rxDoc, + const OUString& rLinkDisplayName, const OUString& sSuffix) : + pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + sLinkSuffix(sSuffix), + sLinkDisplayName(rLinkDisplayName), + 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(sLinkSuffix); + if(sParam.getLength() > sSuffix.getLength() ) + { + OUString sCmp = sParam.copy(sParam.getLength() - sSuffix.getLength(), + sSuffix.getLength()); + if(sCmp == sSuffix) + { + if(pxDoc) + { + sParam = sParam.copy(0, sParam.getLength() - sSuffix.getLength()); + if(!pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); + const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); + + for (size_t i = 0; i < nOutlineCount && !bFound; ++i) + { + const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); + const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); + if(sParam == lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule)) + { + Reference< XPropertySet > xOutline = new SwXOutlineTarget(sParam); + aRet <<= xOutline; + bFound = true; + } + } + } + else + { + aRet = 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(pxDoc) + { + if(!pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + + SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); + const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); + const size_t nOutlineCount = rOutlineNodes.size(); + aRet.realloc(nOutlineCount); + OUString* pResArr = aRet.getArray(); + const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); + for (size_t i = 0; i < nOutlineCount; ++i) + { + OUString sEntry = lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule) + "|outline"; + pResArr[i] = sEntry; + } + } + else + { + Sequence< OUString > aOrg = xRealAccess->getElementNames(); + aRet.realloc(aOrg.getLength()); + std::transform(aOrg.begin(), aOrg.end(), aRet.begin(), + [this](const OUString& rOrg) -> OUString { return rOrg + sLinkSuffix; }); + } + return aRet; +} + +sal_Bool SwXLinkNameAccessWrapper::hasByName(const OUString& rName) +{ + bool bRet = false; + OUString sParam(rName); + if(sParam.getLength() > sLinkSuffix.getLength() ) + { + OUString sCmp = sParam.copy(sParam.getLength() - sLinkSuffix.getLength(), + sLinkSuffix.getLength()); + if(sCmp == sLinkSuffix) + { + sParam = sParam.copy(0, sParam.getLength() - sLinkSuffix.getLength()); + if(pxDoc) + { + if(!pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + SwDoc* pDoc = pxDoc->GetDocShell()->GetDoc(); + const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); + + for (size_t i = 0; i < nOutlineCount && !bRet; ++i) + { + const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); + const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); + if(sParam == + lcl_CreateOutlineString(i, rOutlineNodes, pOutlRule)) + { + bRet = true; + } + } + } + else + { + bRet = xRealAccess->hasByName(sParam); + } + } + } + return bRet; +} + +uno::Type SwXLinkNameAccessWrapper::getElementType() +{ + return cppu::UnoType::get(); +} + +sal_Bool SwXLinkNameAccessWrapper::hasElements() +{ + bool bRet = false; + if(pxDoc) + { + OSL_FAIL("not implemented"); + } + else + { + bRet = xRealAccess->hasElements(); + } + return bRet; +} + +Reference< XPropertySetInfo > SwXLinkNameAccessWrapper::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXLinkNameAccessWrapper::setPropertyValue( + const OUString& rPropName, const Any& ) +{ + throw UnknownPropertyException(rPropName); +} + +static Any lcl_GetDisplayBitmap(const OUString& _sLinkSuffix) +{ + Any aRet; + OUString sLinkSuffix = _sLinkSuffix; + if(!sLinkSuffix.isEmpty()) + sLinkSuffix = sLinkSuffix.copy(1); + OUString sImgId; + + if(sLinkSuffix == "outline") + sImgId = RID_BMP_NAVI_OUTLINE; + else if(sLinkSuffix == "table") + sImgId = RID_BMP_NAVI_TABLE; + else if(sLinkSuffix == "frame") + sImgId = RID_BMP_NAVI_FRAME; + else if(sLinkSuffix == "graphic") + sImgId = RID_BMP_NAVI_GRAPHIC; + else if(sLinkSuffix == "ole") + sImgId = RID_BMP_NAVI_OLE; + else if(sLinkSuffix.isEmpty()) + sImgId = RID_BMP_NAVI_BOOKMARK; + else if(sLinkSuffix == "region") + sImgId = RID_BMP_NAVI_REGION; + + 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 <<= sLinkDisplayName; + } + else if( rPropertyName == UNO_LINK_DISPLAY_BITMAP ) + { + aRet = lcl_GetDisplayBitmap(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(const OUString& rOutlineText) : + pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + sOutlineText(rOutlineText) +{ +} + +SwXOutlineTarget::~SwXOutlineTarget() +{ +} + +Reference< XPropertySetInfo > SwXOutlineTarget::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = 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) + throw UnknownPropertyException(rPropertyName); + + return Any(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 aRet { "com.sun.star.document.LinkTarget" }; + + return aRet; +} + +SwXDocumentPropertyHelper::SwXDocumentPropertyHelper(SwDoc& rDoc) : +SvxUnoForbiddenCharsTable ( rDoc.getIDocumentSettingAccess().getForbiddenCharacterTable() ) +,m_pDoc(&rDoc) +{ +} + +SwXDocumentPropertyHelper::~SwXDocumentPropertyHelper() +{ +} + +Reference SwXDocumentPropertyHelper::GetDrawTable(SwCreateDrawTable nWhich) +{ + Reference xRet; + if(m_pDoc) + { + switch(nWhich) + { + // #i52858# + // assure that Draw model is created, if it doesn't exist. + case SwCreateDrawTable::Dash : + if(!xDashTable.is()) + xDashTable = SvxUnoDashTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xDashTable; + break; + case SwCreateDrawTable::Gradient : + if(!xGradientTable.is()) + xGradientTable = SvxUnoGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xGradientTable; + break; + case SwCreateDrawTable::Hatch : + if(!xHatchTable.is()) + xHatchTable = SvxUnoHatchTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xHatchTable; + break; + case SwCreateDrawTable::Bitmap : + if(!xBitmapTable.is()) + xBitmapTable = SvxUnoBitmapTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xBitmapTable; + break; + case SwCreateDrawTable::TransGradient: + if(!xTransGradientTable.is()) + xTransGradientTable = SvxUnoTransGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xTransGradientTable; + break; + case SwCreateDrawTable::Marker : + if(!xMarkerTable.is()) + xMarkerTable = SvxUnoMarkerTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = xMarkerTable; + break; + case SwCreateDrawTable::Defaults: + if(!xDrawDefaults.is()) + xDrawDefaults = static_cast(new SwSvxUnoDrawPool(m_pDoc)); + xRet = xDrawDefaults; + break; +#if OSL_DEBUG_LEVEL > 0 + default: OSL_FAIL("which table?"); +#endif + } + } + return xRet; +} + +void SwXDocumentPropertyHelper::Invalidate() +{ + xDashTable = nullptr; + xGradientTable = nullptr; + xHatchTable = nullptr; + xBitmapTable = nullptr; + xTransGradientTable = nullptr; + xMarkerTable = nullptr; + 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 000000000..b83a52500 --- /dev/null +++ b/sw/source/uibase/uno/unotxvw.cxx @@ -0,0 +1,1756 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) : + SfxBaseController(pSwView), + m_SelChangedListeners(m_aMutex), + m_pView(pSwView), + m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_VIEW ) ), + mxViewSettings(), + mxTextViewCursor() +{ + +} + +SwXTextView::~SwXTextView() +{ + Invalidate(); +} + +void SwXTextView::Invalidate() +{ + if(mxViewSettings.is()) + { + comphelper::ChainablePropertySet *pSettings = static_cast < comphelper::ChainablePropertySet * > ( mxViewSettings.get() ); + static_cast < SwXViewSettings* > ( pSettings )->Invalidate(); + mxViewSettings.clear(); + } + if(mxTextViewCursor.is()) + { + text::XTextViewCursor* pCursor = mxTextViewCursor.get(); + static_cast(pCursor)->Invalidate(); + mxTextViewCursor.clear(); + } + + osl_atomic_increment(&m_refCount); //prevent second d'tor call + + { + uno::Reference const xInt(static_cast< + cppu::OWeakObject*>(static_cast(this))); + lang::EventObject aEvent(xInt); + m_SelChangedListeners.disposeAndClear(aEvent); + } + + osl_atomic_decrement(&m_refCount); + m_pView = nullptr; +} + +Sequence< uno::Type > SAL_CALL SwXTextView::getTypes( ) +{ + return cppu::OTypeCollection( + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + cppu::UnoType::get(), + SfxBaseController::getTypes() + ).getTypes(); +} + +Sequence< sal_Int8 > SAL_CALL SwXTextView::getImplementationId( ) +{ + return css::uno::Sequence(); +} + +void SAL_CALL SwXTextView::acquire( )throw() +{ + SfxBaseController::acquire(); +} + +void SAL_CALL SwXTextView::release( )throw() +{ + SfxBaseController::release(); +} + +uno::Any SAL_CALL SwXTextView::queryInterface( const uno::Type& aType ) +{ + uno::Any aRet; + if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else if(aType == cppu::UnoType::get()) + { + uno::Reference xRet = this; + aRet <<= xRet; + } + else + aRet = SfxBaseController::queryInterface(aType); + return aRet; +} + +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 sdrObjects; + uno::Reference const xCtrlModel(xInterface, + UNO_QUERY); + if (xCtrlModel.is()) + { + uno::Reference 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 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) + 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 = SwXTextFrame::CreateXTextFrame( + *pFormat->GetDoc(), pFormat); + } + } + break; + case ShellMode::Graphic : + { + SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat(); + if (pFormat) + { + aRef = SwXTextGraphicObject::CreateXTextGraphicObject( + *pFormat->GetDoc(), pFormat); + } + } + break; + case ShellMode::Object : + { + SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat(); + if (pFormat) + { + aRef = SwXTextEmbeddedObject::CreateXTextEmbeddedObject( + *pFormat->GetDoc(), pFormat); + } + } + 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 xShape = SwFmDrawPage::GetShape( pObj ); + xShCol->add(xShape); + } + aRef.set(xShCol, uno::UNO_QUERY); + } + break; + default:;//prevent warning + } + } + uno::Any aRet(&aRef, cppu::UnoType::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, 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 ); + 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< 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(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& rPropList : rRubyList) + { + std::unique_ptr 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(nTmp)); + } + else if(rProperty.Name == UNO_NAME_RUBY_IS_ABOVE) + { + bool bValue = !rProperty.Value.hasValue() || + *o3tl::doAccess(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( /*pPrtDoc, */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( pDocFrame->GetViewShell() ); + pDocView->AttrChangedNotify(nullptr);//So that SelectShell is called. + 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" ); + + uno::Reference const xInt( + static_cast(static_cast(this))); + + lang::EventObject const aEvent(xInt); + m_SelChangedListeners.notifyEach( + &view::XSelectionChangeListener::selectionChanged, aEvent); +} + +namespace { + struct DispatchListener + { + URL const & m_rURL; + Sequence const& m_rSeq; + explicit DispatchListener(URL const& rURL, + Sequence const& rSeq) + : m_rURL(rURL), m_rSeq(rSeq) { } + void operator()(uno::Reference const & xListener) const + { + xListener->dispatch(m_rURL, m_rSeq); + } + }; +} + +void SwXTextView::NotifyDBChanged() +{ + URL aURL; + aURL.Complete = OUString::createFromAscii(SwXDispatch::GetDBChangeURL()); + + m_SelChangedListeners.forEach( + DispatchListener(aURL, Sequence(0))); +} + +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 SfxItemPropertySimpleEntry* 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 SfxItemPropertySimpleEntry* 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 <<= bool(pOpt->GetCoreOptions() & ViewOptFlags1::OnlineSpell); + } + 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 long nY = aCharRect.Top() - (rUL.GetUpper() + DOCUMENTBORDER); + aRet.Y = convertTwipToMm100(nY); + + const SvxLRSpaceItem& rLR = rMaster.GetLRSpace(); + const 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + bRet = m_pView->GetWrtShell().Left( CRSR_SKIP_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", static_cast < cppu::OWeakObject * > ( this ) ); + + bRet = m_pView->GetWrtShell().Right( CRSR_SKIP_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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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(); + } + + uno::Reference xRangeTunnel( xRange, uno::UNO_QUERY); + SwXTextRange* pRange = nullptr; + SwXParagraph* pPara = nullptr; + OTextCursorHelper* pCursor = nullptr; + if(xRangeTunnel.is()) + { + pRange = reinterpret_cast(xRangeTunnel->getSomething( + SwXTextRange::getUnoTunnelId())); + pCursor = reinterpret_cast(xRangeTunnel->getSomething( + OTextCursorHelper::getUnoTunnelId())); + pPara = reinterpret_cast(xRangeTunnel->getSomething( + SwXParagraph::getUnoTunnelId())); + } + + 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.GetNode(). + FindSttNodeByType(eSearchNodeType); + + const SwNode* pSrcNode = nullptr; + if(pCursor && pCursor->GetPaM()) + { + pSrcNode = &pCursor->GetPaM()->GetNode(); + } + else if (pRange) + { + SwPaM aPam(pRange->GetDoc().GetNodes()); + if (pRange->GetPositions(aPam)) + { + pSrcNode = &aPam.GetNode(); + } + } + 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()); + SwPosition* pParamLeft = rDestPam.Start(); + SwPosition* pParamRight = rDestPam.End(); + // 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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(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 SfxPoolItem* pRet = aReq.GetReturnValue(); + bRet = pRet && static_cast(pRet)->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 SfxPoolItem* pRet = aReq.GetReturnValue(); + bRet = pRet && static_cast(pRet)->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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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; + uno::Reference< text::XTextRange > xRet; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", static_cast < cppu::OWeakObject * > ( this ) ); + + 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() " << static_cast(this)); + 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) + { + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", static_cast < cppu::OWeakObject * > ( this ) ); + + 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.GetSwCursor(); + 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->GetNode(); + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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", static_cast < cppu::OWeakObject * > ( this ) ); + + 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" }; +} + +namespace +{ + class theSwXTextViewCursorUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXTextViewCursorUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 > & SwXTextViewCursor::getUnoTunnelId() +{ + return theSwXTextViewCursorUnoTunnelId::get().getSeq(); +} + +//XUnoTunnel +sal_Int64 SAL_CALL SwXTextViewCursor::getSomething( + const uno::Sequence< sal_Int8 >& rId ) +{ + if( isUnoTunnelId(rId) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this )); + } + return OTextCursorHelper::getSomething(rId); +} + +IMPLEMENT_FORWARD_XINTERFACE2(SwXTextViewCursor,SwXTextViewCursor_Base,OTextCursorHelper) +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::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 + { + SwTransferable* pTransfer = new SwTransferable( rSh ); + const bool bLockedView = rSh.IsViewLocked(); + rSh.LockView( true ); //lock visible section + pTransfer->PrepareForCopy(); + rSh.LockView( bLockedView ); + return uno::Reference< datatransfer::XTransferable >( 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/attrdesc.cxx b/sw/source/uibase/utlui/attrdesc.cxx new file mode 100644 index 000000000..a839c436f --- /dev/null +++ b/sw/source/uibase/utlui/attrdesc.cxx @@ -0,0 +1,844 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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() ) + { + 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 +{ + const char* 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 ) + + "(" + GetValue() + ")"; + else + rText = SwResId( STR_NUMRULE_OFF ); + return true; +} + +bool SwParaConnectBorderItem::GetPresentation +( + SfxItemPresentation /*ePres*/, + MapUnit /*eCoreUnit*/, + MapUnit /*ePresUnit*/, + OUString& rText, + const IntlWrapper& /*rIntl*/ +) const +{ + const char* 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() ) + { + const char* 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 +{ + const char* 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 +{ + const char* 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 +{ + const char* pId = nullptr; + 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 +{ + const char* pId = nullptr; + 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 +{ + const char* pId = nullptr; + 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 +{ + const char* pId = nullptr; + 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_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 long nWdth = static_cast(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 +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatEditInReadonly")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr())); + 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 +{ + const char* pId = nullptr; + + 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 +{ + const char* 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: pId = nullptr; 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( 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 ) + { + const char* 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: pId = nullptr; 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 ) + { + const char* 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 ) + { + const char* 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 ) + { + const char* pId = GetValue() ? STR_FOLLOW_TEXT_FLOW : STR_DONT_FOLLOW_TEXT_FLOW; + rText = SwResId(pId); + } + return true; +} + +void SwFormatFollowTextFlow::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatFollowTextFlow")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::boolean(GetValue()).getStr())); + 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 000000000..ea9c1d742 --- /dev/null +++ b/sw/source/uibase/utlui/bookctrl.cxx @@ -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 . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +SFX_IMPL_STATUSBAR_CONTROL( SwBookmarkControl, SfxStringItem ); + +namespace { + +class BookmarkPopup_Impl : public PopupMenu +{ +public: + BookmarkPopup_Impl(); + + sal_uInt16 GetCurId() const { return nCurId; } + +private: + sal_uInt16 nCurId; + + virtual void Select() override; +}; + +} + +BookmarkPopup_Impl::BookmarkPopup_Impl() : + PopupMenu(), + nCurId(USHRT_MAX) +{ +} + +void BookmarkPopup_Impl::Select() +{ + nCurId = GetCurItemId(); +} + +SwBookmarkControl::SwBookmarkControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ) +{ +} + +SwBookmarkControl::~SwBookmarkControl() +{ +} + +void SwBookmarkControl::StateChanged( + sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + if( eState != SfxItemState::DEFAULT || pState->IsVoidItem() ) + GetStatusBar().SetItemText( GetId(), OUString() ); + else if (const SfxStringItem* pStringItem = dynamic_cast(pState)) + { + sPageNumber = pStringItem->GetValue(); + GetStatusBar().SetItemText(GetId(), sPageNumber); + } + else if (const SfxBoolItem* pBoolItem = dynamic_cast(pState)) + { + if (pBoolItem->GetValue()) // Indicates whether to show extended tooltip + GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_BOOKCTRL_HINT_EXTENDED)); + else + GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_BOOKCTRL_HINT)); + } + +} + +void SwBookmarkControl::Paint( const UserDrawEvent& ) +{ +} + +void SwBookmarkControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && + !GetStatusBar().GetItemText( GetId() ).isEmpty() ) + { + ScopedVclPtrInstance aPop; + SwWrtShell* pWrtShell = ::GetActiveWrtShell(); + if( pWrtShell && pWrtShell->getIDocumentMarkAccess()->getAllMarksCount() > 0 ) + { + IDocumentMarkAccess* const pMarkAccess = pWrtShell->getIDocumentMarkAccess(); + IDocumentMarkAccess::const_iterator_t ppBookmarkStart = pMarkAccess->getBookmarksBegin(); + sal_uInt16 nPopupId = 1; + std::map aBookmarkIdx; + for(IDocumentMarkAccess::const_iterator_t ppBookmark = ppBookmarkStart; + ppBookmark != pMarkAccess->getBookmarksEnd(); + ++ppBookmark) + { + if(IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(**ppBookmark)) + { + aPop->InsertItem( nPopupId, (*ppBookmark)->GetName() ); + aBookmarkIdx[nPopupId] = static_cast(ppBookmark - ppBookmarkStart); + nPopupId++; + } + } + aPop->Execute( &GetStatusBar(), rCEvt.GetMousePosPixel()); + sal_uInt16 nCurrId = aPop->GetCurId(); + if( nCurrId != USHRT_MAX) + { + SfxUInt16Item aBookmark( FN_STAT_BOOKMARK, aBookmarkIdx[nCurrId] ); + SfxViewFrame::Current()->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 000000000..df50c63ac --- /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 +#include + +using namespace ::svx; +using namespace ::com::sun::star::uno; + +ConditionEdit::ConditionEdit(std::unique_ptr xControl) + : m_xControl(std::move(xControl)) + , m_aDropTargetHelper(*this) + , bBrackets(true) + , 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 000000000..4729818da --- /dev/null +++ b/sw/source/uibase/utlui/content.cxx @@ -0,0 +1,4033 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#define CTYPE_CNT 0 +#define CTYPE_CTT 1 + +using namespace ::std; +using namespace ::com::sun::star; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; + +namespace { + +constexpr char NAVI_BOOKMARK_DELIM = '\x01'; + +} + +class SwContentArr + : public o3tl::sorted_vector, o3tl::less_uniqueptr_to, + o3tl::find_partialorder_ptrequals> +{ +}; + +namespace +{ + bool lcl_IsContent(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView) + { + return reinterpret_cast(rTreeView.get_id(rEntry).toInt64())->GetTypeId() == CTYPE_CNT; + } + + bool lcl_IsContentType(const weld::TreeIter& rEntry, const weld::TreeView& rTreeView) + { + return reinterpret_cast(rTreeView.get_id(rEntry).toInt64())->GetTypeId() == CTYPE_CTT; + } + + 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; + } + + size_t lcl_InsertURLFieldContent( + SwContentArr *pMember, + SwWrtShell* pWrtShell, + const SwContentType *pCntType) + { + SwGetINetAttrs aArr; + pWrtShell->GetINetAttrs( aArr ); + const SwGetINetAttrs::size_type nCount {aArr.size()}; + for( SwGetINetAttrs::size_type n = 0; n < nCount; ++n ) + { + SwGetINetAttr* p = &aArr[ n ]; + std::unique_ptr pCnt(new SwURLFieldContent( + pCntType, + p->sText, + INetURLObject::decode( + p->rINetAttr.GetINetFormat().GetValue(), + INetURLObject::DecodeMechanism::Unambiguous ), + &p->rINetAttr, + n )); + pMember->insert( std::move(pCnt) ); + } + return nCount; + } +} + +// Content, contains names and reference at the content type. + +SwContent::SwContent(const SwContentType* pCnt, const OUString& rName, long nYPos) : + SwTypeNumber(CTYPE_CNT), + pParent(pCnt), + sContentName(rName), + nYPosition(nYPos), + bInvisible(false) +{ +} + + +SwTypeNumber::~SwTypeNumber() +{ +} + +bool SwContent::IsProtect() const +{ + return false; +} + +bool SwPostItContent::IsProtect() const +{ + return pField->IsProtect(); +} + +bool SwURLFieldContent::IsProtect() const +{ + return pINetAttr->IsProtect(); +} + +SwGraphicContent::~SwGraphicContent() +{ +} + +SwTOXBaseContent::~SwTOXBaseContent() +{ +} + +static const char* 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 +}; + +static const char* 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 +}; + +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; + } +} // 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(nType)])), + m_sSingleContentTypeName(SwResId(STR_CONTENT_TYPE_SINGLE_ARY[static_cast(nType)])), + m_nMemberCount(0), + m_nContentType(nType), + m_nOutlineLevel(nLevel), + m_bDataValid(false), + m_bEdit(false), + m_bDelete(true) +{ + Init(); +} + +void SwContentType::Init(bool* pbInvalidateWindow) +{ + // if the MemberCount is changing ... + size_t nOldMemberCount = m_nMemberCount; + m_nMemberCount = 0; + switch(m_nContentType) + { + case ContentTypeId::OUTLINE : + { + m_sTypeToken = "outline"; + m_nMemberCount = m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); + if (m_nMemberCount < MAXLEVEL) + { + const size_t nOutlineCount = m_nMemberCount; + for(size_t j = 0; j < nOutlineCount; ++j) + { + if (m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(j) > m_nOutlineLevel + || !m_pWrtShell->getIDocumentOutlineNodesAccess()->isOutlineInLayout(j, *m_pWrtShell->GetLayout())) + { + m_nMemberCount --; + } + } + } + } + break; + + case ContentTypeId::TABLE : + m_sTypeToken = "table"; + m_nMemberCount = m_pWrtShell->GetTableFrameFormatCount(true); + m_bEdit = true; + break; + + case ContentTypeId::FRAME : + case ContentTypeId::GRAPHIC : + case ContentTypeId::OLE : + { + FlyCntType eType = FLYCNTTYPE_FRM; + m_sTypeToken = "frame"; + if(m_nContentType == ContentTypeId::OLE) + { + eType = FLYCNTTYPE_OLE; + m_sTypeToken = "ole"; + } + else if(m_nContentType == ContentTypeId::GRAPHIC) + { + eType = FLYCNTTYPE_GRF; + m_sTypeToken = "graphic"; + } + m_nMemberCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true); + m_bEdit = true; + } + break; + case ContentTypeId::BOOKMARK: + { + IDocumentMarkAccess* const pMarkAccess = m_pWrtShell->getIDocumentMarkAccess(); + m_nMemberCount = count_if( + pMarkAccess->getBookmarksBegin(), + pMarkAccess->getBookmarksEnd(), + &lcl_IsUiVisibleBookmark); + m_sTypeToken.clear(); + const bool bProtectedBM = m_pWrtShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS); + m_bEdit = !bProtectedBM; + m_bDelete = !bProtectedBM; + } + break; + case ContentTypeId::REGION : + { + std::unique_ptr pOldMember; + if(!m_pMember) + m_pMember.reset( new SwContentArr ); + else if(!m_pMember->empty()) + { + pOldMember = std::move(m_pMember); + m_pMember.reset( new SwContentArr ); + } + const Point aNullPt; + m_nMemberCount = m_pWrtShell->GetSectionFormatCount(); + for(size_t i = 0; i < m_nMemberCount; ++i) + { + const SwSectionFormat* pFormat; + SectionType eTmpType; + if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() && + (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent + && SectionType::ToxHeader != eTmpType ) + { + const OUString& rSectionName = + pFormat->GetSection()->GetSectionName(); + sal_uInt8 nLevel = 0; + SwSectionFormat* pParentFormat = pFormat->GetParent(); + while(pParentFormat) + { + nLevel++; + pParentFormat = pParentFormat->GetParent(); + } + + std::unique_ptr pCnt(new SwRegionContent(this, rSectionName, + nLevel, + pFormat->FindLayoutRect( false, &aNullPt ).Top())); + + SwPtrMsgPoolItem aAskItem( RES_CONTENT_VISIBLE, nullptr ); + if( !pFormat->GetInfo( aAskItem ) && + !aAskItem.pObject ) // not visible + pCnt->SetInvisible(); + m_pMember->insert(std::move(pCnt)); + } + } + m_nMemberCount = m_pMember->size(); + m_sTypeToken = "region"; + m_bEdit = true; + m_bDelete = false; + if(pOldMember) + { + if(nullptr != pbInvalidateWindow) + { + // 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) + *pbInvalidateWindow = checkVisibilityChanged( + *pOldMember, + *m_pMember); + } + } + } + break; + case ContentTypeId::INDEX: + { + m_nMemberCount = m_pWrtShell->GetTOXCount(); + m_bEdit = true; + m_bDelete = false; + } + break; + case ContentTypeId::REFERENCE: + { + m_nMemberCount = m_pWrtShell->GetRefMarks(); + m_bDelete = false; + } + break; + case ContentTypeId::URLFIELD: + { + m_nMemberCount = 0; + if(!m_pMember) + m_pMember.reset( new SwContentArr ); + else + m_pMember->clear(); + + m_nMemberCount = lcl_InsertURLFieldContent(m_pMember.get(), m_pWrtShell, this); + + m_bEdit = true; + nOldMemberCount = m_nMemberCount; + m_bDelete = true; + } + break; + case ContentTypeId::POSTIT: + { + m_nMemberCount = 0; + if(!m_pMember) + m_pMember.reset( new SwContentArr ); + else + m_pMember->clear(); + + SwPostItMgr* aMgr = m_pWrtShell->GetView().GetPostItMgr(); + if (aMgr) + { + for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i) + { + if (const SwFormatField* pFormatField = dynamic_cast((*i)->GetBroadcaster())) // SwPostit + { + if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc() && + (*i)->mLayoutStatus!=SwPostItHelper::INVISIBLE ) + { + OUString sEntry = pFormatField->GetField()->GetPar2(); + sEntry = RemoveNewline(sEntry); + std::unique_ptr pCnt(new SwPostItContent( + this, + sEntry, + pFormatField, + m_nMemberCount)); + m_pMember->insert(std::move(pCnt)); + m_nMemberCount++; + } + } + } + } + m_sTypeToken.clear(); + m_bEdit = true; + nOldMemberCount = m_nMemberCount; + } + break; + case ContentTypeId::DRAWOBJECT: + { + m_sTypeToken.clear(); + m_bEdit = true; + m_nMemberCount = 0; + SwDrawModel* pModel = m_pWrtShell->getIDocumentDrawModelAccess().GetDrawModel(); + if(pModel) + { + SdrPage* pPage = pModel->GetPage(0); + const size_t nCount = pPage->GetObjCount(); + for( size_t i=0; iGetObj(i); + // #i51726# - all drawing objects can be named now + if (!pTemp->GetName().isEmpty()) + m_nMemberCount++; + } + } + } + break; + default: break; + } + // ... then, the data can also no longer be valid, + // apart from those which have already been corrected, + // then nOldMemberCount is nevertheless not so old. + if( nOldMemberCount != m_nMemberCount ) + m_bDataValid = false; +} + +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* pbLevelOrVisibilityChanged) +{ + std::unique_ptr pOldMember; + size_t nOldMemberCount = 0; + SwPtrMsgPoolItem aAskItem( RES_CONTENT_VISIBLE, nullptr ); + if(m_pMember && pbLevelOrVisibilityChanged) + { + pOldMember = std::move(m_pMember); + nOldMemberCount = pOldMember->size(); + m_pMember.reset( new SwContentArr ); + *pbLevelOrVisibilityChanged = false; + } + else if(!m_pMember) + m_pMember.reset( new SwContentArr ); + else + m_pMember->clear(); + switch(m_nContentType) + { + case ContentTypeId::OUTLINE : + { + const size_t nOutlineCount = m_nMemberCount = + m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineNodesCount(); + + size_t nPos = 0; + for (size_t i = 0; i < nOutlineCount; ++i) + { + const sal_uInt8 nLevel = m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineLevel(i); + if(nLevel >= m_nOutlineLevel ) + m_nMemberCount--; + else + { + if (!m_pWrtShell->getIDocumentOutlineNodesAccess()->isOutlineInLayout(i, *m_pWrtShell->GetLayout())) + { + --m_nMemberCount; + continue; // don't hide it, just skip it + } + OUString aEntry(comphelper::string::stripStart( + m_pWrtShell->getIDocumentOutlineNodesAccess()->getOutlineText(i, m_pWrtShell->GetLayout()), ' ')); + aEntry = SwNavigationPI::CleanEntry(aEntry); + std::unique_ptr pCnt(new SwOutlineContent(this, aEntry, i, nLevel, + m_pWrtShell->IsOutlineMovable( i ), nPos )); + m_pMember->insert(std::move(pCnt)); + // with the same number and existing "pOldMember" the + // old one is compared with the new OutlinePos. + if (nOldMemberCount > nPos && static_cast((*pOldMember)[nPos].get())->GetOutlineLevel() != nLevel) + *pbLevelOrVisibilityChanged = true; + + nPos++; + } + } + + } + break; + + case ContentTypeId::TABLE : + { + const size_t nCount = m_pWrtShell->GetTableFrameFormatCount(true); + OSL_ENSURE(m_nMemberCount == nCount, "MemberCount differs"); + Point aNullPt; + m_nMemberCount = nCount; + for(size_t i = 0; i < m_nMemberCount; ++i) + { + const SwFrameFormat& rTableFormat = m_pWrtShell->GetTableFrameFormat(i, true); + const OUString& sTableName( rTableFormat.GetName() ); + + SwContent* pCnt = new SwContent(this, sTableName, + rTableFormat.FindLayoutRect(false, &aNullPt).Top() ); + if( !rTableFormat.GetInfo( aAskItem ) && + !aAskItem.pObject ) // not visible + pCnt->SetInvisible(); + + m_pMember->insert(std::unique_ptr(pCnt)); + + if(nOldMemberCount > i && + (*pOldMember)[i]->IsInvisible() != pCnt->IsInvisible()) + *pbLevelOrVisibilityChanged = true; + } + } + 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; + m_nMemberCount = m_pWrtShell->GetFlyCount(eType, /*bIgnoreTextBoxes=*/true); + std::vector formats(m_pWrtShell->GetFlyFrameFormats(eType, /*bIgnoreTextBoxes=*/true)); + SAL_WARN_IF(m_nMemberCount != formats.size(), "sw.ui", "MemberCount differs"); + m_nMemberCount = formats.size(); + for (size_t i = 0; i < m_nMemberCount; ++i) + { + SwFrameFormat const*const pFrameFormat = formats[i]; + const OUString sFrameName = pFrameFormat->GetName(); + + SwContent* pCnt; + if(ContentTypeId::GRAPHIC == m_nContentType) + { + OUString sLink; + m_pWrtShell->GetGrfNms( &sLink, nullptr, static_cast( pFrameFormat)); + pCnt = new SwGraphicContent(this, sFrameName, + INetURLObject::decode( sLink, + INetURLObject::DecodeMechanism::Unambiguous ), + pFrameFormat->FindLayoutRect(false, &aNullPt).Top()); + } + else + { + pCnt = new SwContent(this, sFrameName, + pFrameFormat->FindLayoutRect(false, &aNullPt).Top() ); + } + if( !pFrameFormat->GetInfo( aAskItem ) && + !aAskItem.pObject ) // not visible + pCnt->SetInvisible(); + m_pMember->insert(std::unique_ptr(pCnt)); + if (nOldMemberCount > i && + (*pOldMember)[i]->IsInvisible() != pCnt->IsInvisible()) + *pbLevelOrVisibilityChanged = true; + } + } + break; + case ContentTypeId::BOOKMARK: + { + 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 + std::unique_ptr pCnt(new SwContent(this, rBkmName, 0)); + m_pMember->insert(std::move(pCnt)); + } + } + } + break; + case ContentTypeId::REGION : + { + const Point aNullPt; + m_nMemberCount = m_pWrtShell->GetSectionFormatCount(); + for(size_t i = 0; i < m_nMemberCount; ++i) + { + const SwSectionFormat* pFormat; + SectionType eTmpType; + if( (pFormat = &m_pWrtShell->GetSectionFormat(i))->IsInNodesArr() && + (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent + && SectionType::ToxHeader != eTmpType ) + { + OUString sSectionName = pFormat->GetSection()->GetSectionName(); + + sal_uInt8 nLevel = 0; + SwSectionFormat* pParentFormat = pFormat->GetParent(); + while(pParentFormat) + { + nLevel++; + pParentFormat = pParentFormat->GetParent(); + } + + std::unique_ptr pCnt(new SwRegionContent(this, sSectionName, + nLevel, + pFormat->FindLayoutRect( false, &aNullPt ).Top())); + if( !pFormat->GetInfo( aAskItem ) && + !aAskItem.pObject ) // not visible + pCnt->SetInvisible(); + m_pMember->insert(std::move(pCnt)); + } + + if(nullptr != pbLevelOrVisibilityChanged) + { + assert(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) + *pbLevelOrVisibilityChanged = checkVisibilityChanged( + *pOldMember, + *m_pMember); + } + } + m_nMemberCount = m_pMember->size(); + } + break; + case ContentTypeId::REFERENCE: + { + std::vector aRefMarks; + m_nMemberCount = m_pWrtShell->GetRefMarks( &aRefMarks ); + + for (const auto& rRefMark : aRefMarks) + { + // References sorted alphabetically + m_pMember->insert(std::make_unique(this, rRefMark, 0)); + } + } + break; + case ContentTypeId::URLFIELD: + m_nMemberCount = lcl_InsertURLFieldContent(m_pMember.get(), m_pWrtShell, this); + break; + case ContentTypeId::INDEX: + { + + const sal_uInt16 nCount = m_pWrtShell->GetTOXCount(); + m_nMemberCount = nCount; + 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, nTox, *pBase); + + if( !pBase->GetInfo( aAskItem ) && + !aAskItem.pObject ) // not visible + pCnt->SetInvisible(); + + m_pMember->insert( std::unique_ptr(pCnt) ); + const size_t nPos = m_pMember->size() - 1; + if(nOldMemberCount > nPos && + (*pOldMember)[nPos]->IsInvisible() + != pCnt->IsInvisible()) + *pbLevelOrVisibilityChanged = true; + } + } + break; + case ContentTypeId::POSTIT: + { + m_nMemberCount = 0; + m_pMember->clear(); + SwPostItMgr* aMgr = m_pWrtShell->GetView().GetPostItMgr(); + if (aMgr) + { + for(SwPostItMgr::const_iterator i = aMgr->begin(); i != aMgr->end(); ++i) + { + if (const SwFormatField* pFormatField = dynamic_cast((*i)->GetBroadcaster())) // SwPostit + { + if (pFormatField->GetTextField() && pFormatField->IsFieldInDoc() && + (*i)->mLayoutStatus!=SwPostItHelper::INVISIBLE ) + { + OUString sEntry = pFormatField->GetField()->GetPar2(); + sEntry = RemoveNewline(sEntry); + std::unique_ptr pCnt(new SwPostItContent( + this, + sEntry, + pFormatField, + m_nMemberCount)); + m_pMember->insert(std::move(pCnt)); + m_nMemberCount++; + } + } + } + } + } + break; + case ContentTypeId::DRAWOBJECT: + { + m_nMemberCount = 0; + m_pMember->clear(); + + IDocumentDrawModelAccess& rIDDMA = m_pWrtShell->getIDocumentDrawModelAccess(); + SwDrawModel* pModel = rIDDMA.GetDrawModel(); + if(pModel) + { + SdrPage* pPage = pModel->GetPage(0); + const size_t nCount = pPage->GetObjCount(); + for( size_t i=0; iGetObj(i); + // #i51726# - all drawing objects can be named now + if (!pTemp->GetName().isEmpty()) + { + SwContact* pContact = static_cast(pTemp->GetUserCall()); + long nYPos = 0; + const Point aNullPt; + if(pContact && pContact->GetFormat()) + nYPos = pContact->GetFormat()->FindLayoutRect(false, &aNullPt).Top(); + SwContent* pCnt = new SwContent( + this, + pTemp->GetName(), + nYPos); + if(!rIDDMA.IsVisibleLayerId(pTemp->GetLayer())) + pCnt->SetInvisible(); + m_pMember->insert(std::unique_ptr(pCnt)); + m_nMemberCount++; + if (nOldMemberCount > i && + (*pOldMember)[i]->IsInvisible() != pCnt->IsInvisible() ) + *pbLevelOrVisibilityChanged = true; + } + } + } + } + break; + default: break; + } + 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 +}; + +} + +static const char* 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 xTreeView, SwNavigationPI* pDialog) + : m_xTreeView(std::move(xTreeView)) + , m_aDropTargetHelper(*this) + , m_xDialog(pDialog) + , m_sSpace(OUString(" ")) + , 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) +{ + Size aSize(m_xDialog->LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont))); + m_xTreeView->set_size_request(aSize.Width(), aSize.Height()); + + 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, FocusHdl)); + 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)); + + for (ContentTypeId i : o3tl::enumrange()) + { + 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(); + m_aUpdTimer.SetInvokeHandler(LINK(this, SwContentTree, TimerUpdate)); + m_aUpdTimer.SetTimeout(1000); +} + +SwContentTree::~SwContentTree() +{ + clear(); // If applicable erase content types previously. + m_aUpdTimer.Stop(); + SetActiveShell(nullptr); + m_xDialog.clear(); +} + +// 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 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 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 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); + } + + return nAccept; +} + +bool SwContentTree::IsInDrag() const +{ + return m_xTreeView->get_drag_source() == m_xTreeView.get(); +} + +// 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(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 xDropEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get())) + xDropEntry.reset(); + + if (m_nRootType == ContentTypeId::OUTLINE) + { + if (xDropEntry && lcl_IsContent(*xDropEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xDropEntry).toInt64()))); + SwOutlineContent* pOutlineContent = reinterpret_cast(m_xTreeView->get_id(*xDropEntry).toInt64()); + assert(pOutlineContent); + + void* key = lcl_GetOutlineKey(*this, pOutlineContent); + assert(key); + if (!mOutLineNodeMap[key]) + { + while (m_xTreeView->iter_has_child(*xDropEntry)) + { + std::unique_ptr 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(reinterpret_cast(m_xTreeView->get_id(*xDropEntry).toInt64()))); + nTargetPos = reinterpret_cast(m_xTreeView->get_id(*xDropEntry).toInt64())->GetOutlinePos(); + } + + if( MAXLEVEL > m_nOutlineLevel && // Not all layers are displayed. + nTargetPos != SwOutlineNodes::npos) + { + std::unique_ptr xNext(m_xTreeView->make_iterator(xDropEntry.get())); + bool bNext = m_xTreeView->iter_next(*xNext); + if (bNext) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xNext).toInt64()))); + nTargetPos = reinterpret_cast(m_xTreeView->get_id(*xNext).toInt64())->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 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(weld::TreeView& rContentTree, weld::TreeIter& rEntry, weld::Menu& rPop) +{ + if (rContentTree.iter_has_child(rEntry) || rContentTree.get_children_on_demand(rEntry)) + { + rPop.set_label(OString::number(800), IsAllExpanded(rContentTree, rEntry) ? SwResId(STR_COLLAPSEALL) : SwResId(STR_EXPANDALL)); + return false; + } + return true; +} + +IMPL_LINK(SwContentTree, CommandHdl, const CommandEvent&, rCEvt, bool) +{ + if (rCEvt.GetCommand() != CommandEventId::ContextMenu) + return false; + + std::unique_ptr xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/navigatorcontextmenu.ui")); + std::unique_ptr xPop = xBuilder->weld_menu("navmenu"); + + bool bOutline(false); + std::unique_ptr xSubPop1 = xBuilder->weld_menu("outlinelevel"); + std::unique_ptr xSubPop2 = xBuilder->weld_menu("dragmodemenu"); + std::unique_ptr xSubPop3 = xBuilder->weld_menu("displaymenu"); + std::unique_ptr xSubPopOutlineTracking = xBuilder->weld_menu("outlinetracking"); + + for(int i = 1; i <= 3; ++i) + xSubPopOutlineTracking->append_radio(OUString::number(i + 10), m_aContextStrings[IDX_STR_OUTLINE_TRACKING + i]); + xSubPopOutlineTracking->set_active(OString::number(10 + m_nOutlineTracking), true); + + for (int i = 1; i <= MAXLEVEL; ++i) + xSubPop1->append_radio(OUString::number(i + 100), OUString::number(i)); + xSubPop1->set_active(OString::number(100 + m_nOutlineLevel), true); + + for (int i=0; i < 3; ++i) + xSubPop2->append_radio(OUString::number(i + 201), m_aContextStrings[IDX_STR_HYPERLINK + i]); + xSubPop2->set_active(OString::number(201 + static_cast(GetParentWindow()->GetRegionDropMode())), true); + + // Insert the list of the open files + sal_uInt16 nId = 301; + const SwView* pActiveView = ::GetActiveView(); + SwView *pView = SwModule::GetFirstView(); + while (pView) + { + OUString sInsert = pView->GetDocShell()->GetTitle(); + if (pView == pActiveView) + { + sInsert += "(" + + m_aContextStrings[IDX_STR_ACTIVE] + + ")"; + } + xSubPop3->append_radio(OUString::number(nId), sInsert); + if (State::CONSTANT == m_eState && m_pActiveShell == &pView->GetWrtShell()) + xSubPop3->set_active(OString::number(nId), true); + pView = SwModule::GetNextView(pView); + nId++; + } + xSubPop3->append_radio(OUString::number(nId++), m_aContextStrings[IDX_STR_ACTIVE_VIEW]); + if (m_pHiddenShell) + { + OUString sHiddenEntry = m_pHiddenShell->GetView().GetDocShell()->GetTitle() + + " ( " + + m_aContextStrings[IDX_STR_HIDDEN] + + " )"; + xSubPop3->append_radio(OUString::number(nId), sHiddenEntry); + } + + if (State::ACTIVE == m_eState) + xSubPop3->set_active(OString::number(--nId), true); + else if (State::HIDDEN == m_eState) + xSubPop3->set_active(OString::number(nId), true); + + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xEntry.get())) + xEntry.reset(); + + if (!xEntry || !lcl_IsContent(*xEntry, *m_xTreeView)) + xPop->remove(OString::number(900)); // go to + + bool bRemovePostItEntries = true; + bool bRemoveIndexEntries = true; + bool bRemoveEditEntry = true; + bool bRemoveUnprotectEntry = true; + bool bRemoveDeleteEntry = true; + bool bRemoveRenameEntry = true; + bool bRemoveSelectEntry = true; + bool bRemoveToggleExpandEntry = true; + bool bRemoveChapterEntries = true; + bool bRemoveSendOutlineEntry = true; + + // Edit only if the shown content is coming from the current view. + if ((State::ACTIVE == m_eState || m_pActiveShell == pActiveView->GetWrtShellPtr()) + && xEntry && lcl_IsContent(*xEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + const SwContentType* pContType = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetParent(); + const ContentTypeId nContentType = pContType->GetType(); + const bool bReadonly = m_pActiveShell->GetView().GetDocShell()->IsReadOnly(); + const bool bVisible = !reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->IsInvisible(); + const bool bProtected = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->IsProtect(); + const bool bProtectBM = (ContentTypeId::BOOKMARK == nContentType) + && m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS); + const bool bEditable = pContType->IsEditable() && + ((bVisible && !bProtected && !bProtectBM) || ContentTypeId::REGION == nContentType); + const bool bDeletable = pContType->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); + + if (!bReadonly && (bEditable || bDeletable)) + { + if(ContentTypeId::INDEX == nContentType) + { + bRemoveIndexEntries = false; + + const SwTOXBase* pBase = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetTOXBase(); + if (!pBase->IsTOXBaseInReadonly()) + bRemoveEditEntry = false; + + xPop->set_active(OString::number(405), SwEditShell::IsTOXBaseReadonly(*pBase)); + bRemoveDeleteEntry = false; + } + else if(ContentTypeId::TABLE == nContentType) + { + bRemoveSelectEntry = false; + bRemoveEditEntry = false; + bRemoveUnprotectEntry = false; + bool bFull = false; + OUString sTableName = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetName(); + bool bProt = m_pActiveShell->HasTableAnyProtection( &sTableName, &bFull ); + xPop->set_sensitive(OString::number(403), !bFull); + xPop->set_sensitive(OString::number(404), bProt); + bRemoveDeleteEntry = false; + } + else if(ContentTypeId::OUTLINE == nContentType) + { + bOutline = true; + bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop); + bRemoveSelectEntry = false; + bRemoveChapterEntries = false; + } + else if(ContentTypeId::DRAWOBJECT == nContentType) + { + bRemoveDeleteEntry = false; + } + else if(ContentTypeId::REGION == nContentType) + { + bRemoveSelectEntry = false; + bRemoveEditEntry = false; + } + else + { + if (bEditable && bDeletable) + { + bRemoveEditEntry = false; + bRemoveDeleteEntry = false; + } + else if (bEditable) + bRemoveEditEntry = false; + else if (bDeletable) + { + bRemoveDeleteEntry = false; + } + } + //Rename object + if (bRenamable) + bRemoveRenameEntry = false; + } + } + else if (xEntry) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + SwContentType* pType = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()); + if (ContentTypeId::OUTLINE == pType->GetType()) + { + bOutline = true; + bRemoveToggleExpandEntry = lcl_InsertExpandCollapseAllItem(*m_xTreeView, *xEntry, *xPop); + bRemoveSendOutlineEntry = false; + } + if ( (pType->GetType() == ContentTypeId::POSTIT) && (!m_pActiveShell->GetView().GetDocShell()->IsReadOnly()) && ( pType->GetMemberCount() > 0) ) + bRemovePostItEntries = false; + } + + if (bRemoveToggleExpandEntry) + { + xPop->remove("separator3"); + xPop->remove(OString::number(800)); + } + + if (bRemoveSelectEntry) + xPop->remove(OString::number(805)); + + if (bRemoveChapterEntries) + { + xPop->remove("separator2"); + xPop->remove(OString::number(806)); + xPop->remove(OString::number(801)); + xPop->remove(OString::number(802)); + xPop->remove(OString::number(803)); + xPop->remove(OString::number(804)); + } + + if (bRemoveSendOutlineEntry) + xPop->remove(OString::number(700)); + + if (bRemovePostItEntries) + { + xPop->remove(OString::number(600)); + xPop->remove(OString::number(601)); + xPop->remove(OString::number(602)); + } + + if (bRemoveDeleteEntry) + xPop->remove(OString::number(501)); + + if (bRemoveRenameEntry) + xPop->remove(OString::number(502)); + + if (bRemoveIndexEntries) + { + xPop->remove(OString::number(401)); + xPop->remove(OString::number(402)); + xPop->remove(OString::number(405)); + } + + if (bRemoveUnprotectEntry) + xPop->remove(OString::number(404)); + + if (bRemoveEditEntry) + xPop->remove(OString::number(403)); + + if (bRemoveToggleExpandEntry && + bRemoveSelectEntry && + bRemoveChapterEntries && + bRemoveSendOutlineEntry && + bRemovePostItEntries && + bRemoveDeleteEntry && + bRemoveRenameEntry && + bRemoveIndexEntries && + bRemoveUnprotectEntry && + bRemoveEditEntry) + { + xPop->remove("separator1"); + } + + if (!bOutline) + { + xSubPop1.reset(); + xPop->remove(OString::number(1)); // outline level menu + xSubPopOutlineTracking.reset(); + xPop->remove(OString::number(4)); // outline tracking menu + } + + OString sCommand = xPop->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))); + if (!sCommand.isEmpty()) + ExecuteContextMenuAction(sCommand); + + return true; +} + +void SwContentTree::insert(const weld::TreeIter* pParent, const OUString& rStr, const OUString& rId, + const OUString* pExpanderName, bool bChildrenOnDemand, weld::TreeIter* pRet) +{ + m_xTreeView->insert(pParent, -1, &rStr, &rId, nullptr, nullptr, pExpanderName, bChildrenOnDemand, pRet); + ++m_nEntryCount; +} + +void SwContentTree::remove(const weld::TreeIter& rIter) +{ + if (m_xTreeView->iter_has_child(rIter)) + { + std::unique_ptr 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) +{ + bool bChild = m_xTreeView->iter_has_child(rParent); + if (bChild || !m_xTreeView->get_children_on_demand(rParent)) + return bChild; + + // Is this a content type? + if (lcl_IsContentType(rParent, *m_xTreeView)) + { + std::unique_ptr xChild = m_xTreeView->make_iterator(); + + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()))); + SwContentType* pCntType = reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()); + + const size_t nCount = pCntType->GetMemberCount(); + // Add for outline plus/minus + if (pCntType->GetType() == ContentTypeId::OUTLINE) + { + for(size_t i = 0; i < nCount; ++i) + { + const SwContent* pCnt = pCntType->GetMember(i); + if(pCnt) + { + const auto nLevel = static_cast(pCnt)->GetOutlineLevel(); + OUString sEntry = pCnt->GetName(); + if(sEntry.isEmpty()) + sEntry = m_sSpace; + OUString sId(OUString::number(reinterpret_cast(pCnt))); + if (!bChild || (nLevel == 0)) + { + insert(&rParent, sEntry, sId, nullptr, 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)); + bChild = true; + } + else + { + //back search parent. + if(static_cast(pCntType->GetMember(i-1))->GetOutlineLevel() < nLevel) + { + insert(xChild.get(), sEntry, sId, nullptr, 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)); + bChild = true; + } + else + { + bChild = m_xTreeView->iter_previous(*xChild); + assert(!bChild || lcl_IsContentType(*xChild, *m_xTreeView) || dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xChild).toInt64()))); + while (bChild && + lcl_IsContent(*xChild, *m_xTreeView) && + (reinterpret_cast(m_xTreeView->get_id(*xChild).toInt64())->GetOutlineLevel() >= nLevel) + ) + { + bChild = m_xTreeView->iter_previous(*xChild); + } + if (bChild) + { + insert(xChild.get(), sEntry, sId, nullptr, 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)); + } + } + } + } + } + } + else + { + bool bRegion = pCntType->GetType() == ContentTypeId::REGION; + for(size_t i = 0; i < nCount; ++i) + { + const SwContent* pCnt = pCntType->GetMember(i); + if (pCnt) + { + OUString sEntry = pCnt->GetName(); + if (sEntry.isEmpty()) + sEntry = m_sSpace; + OUString sId(OUString::number(reinterpret_cast(pCnt))); + insert(&rParent, sEntry, sId, nullptr, false, xChild.get()); + m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible()); + if (bRegion) + m_xTreeView->set_extra_row_indent(*xChild, static_cast(pCnt)->GetRegionLevel()); + bChild = true; + } + } + } + } + + return bChild; +} + +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); + const size_t nCount = pPage->GetObjCount(); + + for( size_t i=0; iGetObj(i); + if( pTemp->GetName() == pCnt->GetName()) + { + pRetObj = pTemp; + break; + } + } + } + break; + } + default: + pRetObj = nullptr; + } + return pRetObj; +} + +void SwContentTree::Expand(const weld::TreeIter& rParent, std::vector>* pNodesToExpand) +{ + if (!(m_xTreeView->iter_has_child(rParent) || m_xTreeView->get_children_on_demand(rParent))) + return; + + if (!m_bIsRoot + || (lcl_IsContentType(rParent, *m_xTreeView) && + reinterpret_cast(m_xTreeView->get_id(rParent).toInt64())->GetType() == ContentTypeId::OUTLINE) + || (m_nRootType == ContentTypeId::OUTLINE)) + { + if (lcl_IsContentType(rParent, *m_xTreeView)) + { + SwContentType* pCntType = reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()); + const sal_Int32 nOr = 1 << static_cast(pCntType->GetType()); //linear -> Bitposition + if (State::HIDDEN != m_eState) + { + m_nActiveBlock |= nOr; + m_pConfig->SetActiveBlock(m_nActiveBlock); + } + else + m_nHiddenBlock |= nOr; + if (pCntType->GetType() == ContentTypeId::OUTLINE) + { + std::map< void*, bool > aCurrOutLineNodeMap; + + SwWrtShell* pShell = GetWrtShell(); + bool bParentHasChild = RequestingChildren(rParent); + if (pNodesToExpand) + pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&rParent)); + if (bParentHasChild) + { + std::unique_ptr 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(reinterpret_cast(m_xTreeView->get_id(*xChild).toInt64()))); + auto const nPos = reinterpret_cast(m_xTreeView->get_id(*xChild).toInt64())->GetOutlinePos(); + void* key = static_cast(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos )); + aCurrOutLineNodeMap.emplace( key, false ); + std::map::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 + { + if (lcl_IsContent(rParent, *m_xTreeView)) + { + SwWrtShell* pShell = GetWrtShell(); + // paranoid assert now that outline type is checked + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()))); + auto const nPos = reinterpret_cast(m_xTreeView->get_id(rParent).toInt64())->GetOutlinePos(); + void* key = static_cast(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos )); + mOutLineNodeMap[key] = true; + } + } + } + + RequestingChildren(rParent); + if (pNodesToExpand) + pNodesToExpand->emplace_back(m_xTreeView->make_iterator(&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 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 + } + SwContentType* pCntType = reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()); + const sal_Int32 nAnd = ~(1 << static_cast(pCntType->GetType())); + if (State::HIDDEN != m_eState) + { + m_nActiveBlock &= nAnd; + m_pConfig->SetActiveBlock(m_nActiveBlock); + } + else + m_nHiddenBlock &= nAnd; + } + else if (lcl_IsContent(rParent, *m_xTreeView)) + { + SwWrtShell* pShell = GetWrtShell(); + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(rParent).toInt64()))); + auto const nPos = reinterpret_cast(m_xTreeView->get_id(rParent).toInt64())->GetOutlinePos(); + void* key = static_cast(pShell->getIDocumentOutlineNodesAccess()->getOutlineNode( nPos )); + mOutLineNodeMap[key] = false; + } + + return true; +} + +// Also on double click will be initially opened only. +IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool) +{ + bool bConsumed = false; + + std::unique_ptr 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)) + { + if (State::CONSTANT == m_eState) + { + m_pActiveShell->GetView().GetViewFrame()->GetWindow().ToTop(); + } + //Jump to content type: + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + SwContent* pCnt = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()); + assert(pCnt && "no UserData"); + GotoContent(pCnt); + const ContentTypeId nActType = pCnt->GetParent()->GetType(); + if (nActType == ContentTypeId::FRAME) + m_pActiveShell->EnterStdMode(); + // fdo#36308 don't expand outlines on double-click + bConsumed = nActType == ContentTypeId::OUTLINE; + } + } + + return bConsumed; // false/true == allow/disallow more to be done, i.e. expand/collapse children +} + +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::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 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 SwContentTree::GetEntryAtAbsPos(size_t nAbsPos) const +{ + std::unique_ptr 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 xOldSelEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xOldSelEntry.get())) + xOldSelEntry.reset(); + OUString sEntryName; // Name of the entry + size_t nEntryRelPos = 0; // relative position to their parent + size_t nOldEntryCount = GetEntryCount(); + sal_Int32 nOldScrollPos = 0; + if (xOldSelEntry) + { + UpdateLastSelType(); + + nOldScrollPos = m_xTreeView->vadjustment_get_value(); + sEntryName = m_xTreeView->get_text(*xOldSelEntry); + std::unique_ptr 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_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_xContent3ToolBox->set_item_sensitive("chapterup", !bDisable); + pNavi->m_xContent3ToolBox->set_item_sensitive("chapterdown", !bDisable); + pNavi->m_xContent3ToolBox->set_item_sensitive("promote", !bDisable); + pNavi->m_xContent3ToolBox->set_item_sensitive("demote", !bDisable); + pNavi->m_xContent2ToolBox->set_item_sensitive("reminder", !bDisable); + } + + if (pShell) + { + std::unique_ptr xEntry = m_xTreeView->make_iterator(); + std::unique_ptr xSelEntry; + // all content navigation view + if(m_nRootType == ContentTypeId::UNKNOWN) + { + m_xTreeView->freeze(); + + std::vector> aNodesToExpand; + + for( ContentTypeId nCntType : o3tl::enumrange() ) + { + std::unique_ptr& rpContentT = bActive ? + m_aActiveContentArr[nCntType] : + m_aHiddenContentArr[nCntType]; + if(!rpContentT) + rpContentT.reset(new SwContentType(pShell, nCntType, m_nOutlineLevel )); + + OUString sEntry = rpContentT->GetName(); + OUString aImage(GetImageIdForContentTypeId(nCntType)); + bool bChOnDemand = 0 != rpContentT->GetMemberCount(); + OUString sId(OUString::number(reinterpret_cast(rpContentT.get()))); + insert(nullptr, sEntry, sId, &aImage, bChOnDemand, xEntry.get()); + + m_xTreeView->set_sensitive(*xEntry, bChOnDemand); + + if (nCntType == m_nLastSelType) + xSelEntry = m_xTreeView->make_iterator(xEntry.get()); + sal_Int32 nExpandOptions = (State::HIDDEN == m_eState) + ? m_nHiddenBlock + : m_nActiveBlock; + if (nExpandOptions & (1 << static_cast(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); + + (void)m_xTreeView->get_iter_first(*xEntry); + for (ContentTypeId nCntType : o3tl::enumrange()) + { + sal_Int32 nExpandOptions = (State::HIDDEN == m_eState) + ? m_nHiddenBlock + : m_nActiveBlock; + if (nExpandOptions & (1 << static_cast(nCntType))) + { + if (nEntryRelPos && nCntType == m_nLastSelType) + { + // reselect the entry + std::unique_ptr xChild(m_xTreeView->make_iterator(xEntry.get())); + std::unique_ptr xTemp; + sal_uLong nPos = 1; + while (m_xTreeView->iter_next(*xChild)) + { + // The old text will be slightly favored + if (sEntryName == m_xTreeView->get_text(*xChild) || + nPos == nEntryRelPos) + { + m_xTreeView->copy_iterator(*xChild, *xSelEntry); + break; + } + xTemp = m_xTreeView->make_iterator(xChild.get()); + nPos++; + } + if (!xSelEntry || lcl_IsContentType(*xSelEntry, *m_xTreeView)) + xSelEntry = std::move(xTemp); + } + } + + (void)m_xTreeView->iter_next_sibling(*xEntry); + } + + if (!xSelEntry) + { + nOldScrollPos = 0; + xSelEntry = m_xTreeView->make_iterator(); + if (!m_xTreeView->get_iter_first(*xSelEntry)) + xSelEntry.reset(); + } + + if (xSelEntry) + { + m_xTreeView->set_cursor(*xSelEntry); + Select(); + } + } + // root content navigation view + else + { + m_xTreeView->freeze(); + + std::unique_ptr& 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; + OUString sId(OUString::number(reinterpret_cast(rpRootContentT.get()))); + insert(nullptr, rpRootContentT->GetName(), sId, &aImage, bChOnDemand, xEntry.get()); + + if (!bChOnDemand) + { + bool bRegion = rpRootContentT->GetType() == ContentTypeId::REGION; + + std::unique_ptr xChild = m_xTreeView->make_iterator(); + for (size_t i = 0; i < rpRootContentT->GetMemberCount(); ++i) + { + const SwContent* pCnt = rpRootContentT->GetMember(i); + if (pCnt) + { + OUString sEntry = pCnt->GetName(); + if(sEntry.isEmpty()) + sEntry = m_sSpace; + OUString sSubId(OUString::number(reinterpret_cast(pCnt))); + insert(xEntry.get(), sEntry, sSubId, nullptr, false, xChild.get()); + m_xTreeView->set_sensitive(*xChild, !pCnt->IsInvisible()); + if (bRegion) + m_xTreeView->set_extra_row_indent(*xChild, static_cast(pCnt)->GetRegionLevel()); + } + } + } + else + { + RequestingChildren(*xEntry); + m_xTreeView->set_children_on_demand(*xEntry, false); + } + + m_xTreeView->set_sensitive(*xEntry, m_xTreeView->iter_has_child(*xEntry)); + + m_xTreeView->thaw(); + + m_xTreeView->expand_row(*xEntry); + + // reselect the entry + if (nEntryRelPos) + { + std::unique_ptr xChild(m_xTreeView->make_iterator(xEntry.get())); + sal_uLong nPos = 1; + while (m_xTreeView->iter_next(*xChild)) + { + // The old text will be slightly favored + if (sEntryName == m_xTreeView->get_text(*xChild) || nPos == nEntryRelPos) + { + xSelEntry = std::move(xChild); + break; + } + nPos++; + } + if (xSelEntry) + { + m_xTreeView->set_cursor(*xSelEntry); // unselect all entries, make pSelEntry visible, and select + Select(); + } + } + else + { + m_xTreeView->set_cursor(*xEntry); + Select(); + } + } + } + + if (!m_bIsInPromoteDemote && 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 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(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + SwContent* pCnt = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()); + + 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(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(pCnt)->IsMoveable(); + bOutline = true; + } + } + break; + case ContentTypeId::POSTIT: + case ContentTypeId::INDEX: + case ContentTypeId::REFERENCE : + // cannot be inserted, neither as URL nor as section + break; + case ContentTypeId::URLFIELD: + sUrl = static_cast(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 xEntry(m_xTreeView->make_iterator()); + bool bEntry = m_xTreeView->get_cursor(xEntry.get()); + const SwContentType* pCntType; + if (bEntry) + { + if (lcl_IsContentType(*xEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + pCntType = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()); + } + else + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + pCntType = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetParent(); + } + m_nRootType = pCntType->GetType(); + m_bIsRoot = true; + Display(State::HIDDEN != m_eState); + if (m_nRootType == ContentTypeId::OUTLINE) + { + m_xTreeView->set_selection_mode(SelectionMode::Multiple); + } + } + } + else + { + m_xTreeView->set_selection_mode(SelectionMode::Single); + m_nRootType = ContentTypeId::UNKNOWN; + m_bIsRoot = false; + FindActiveTypeAndRemoveUserData(); + Display(State::HIDDEN != m_eState); + } + m_pConfig->SetRootType( m_nRootType ); + weld::Toolbar* pBox = GetParentWindow()->m_xContent2ToolBox.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. + + // bVisibilityChanged gets set to true if some element, like a section, + // changed visibility and should have its name rerendered with a new + // grayed-out state + bool bVisibilityChanged = false; + + if (State::HIDDEN == m_eState) + { + for(ContentTypeId i : o3tl::enumrange()) + { + if(m_aActiveContentArr[i]) + m_aActiveContentArr[i]->Invalidate(); + } + } + // root content navigation view + else if(m_bIsRoot) + { + std::unique_ptr xRootEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_iter_first(*xRootEntry)) + bContentChanged = true; + else + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xRootEntry).toInt64()))); + const ContentTypeId nType = reinterpret_cast(m_xTreeView->get_id(*xRootEntry).toInt64())->GetType(); + SwContentType* pArrType = m_aActiveContentArr[nType].get(); + if (!pArrType) + bContentChanged = true; + else + { + // start check if first selected outline level has changed + bool bCheckChanged = m_nRootType == ContentTypeId::OUTLINE && !m_xTreeView->has_focus(); + if (bCheckChanged) + { + std::unique_ptr xFirstSel(m_xTreeView->make_iterator()); + bool bFirstSel = m_xTreeView->get_selected(xFirstSel.get()); + if (bFirstSel && lcl_IsContent(*xFirstSel, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xFirstSel).toInt64()))); + const auto nSelLevel = reinterpret_cast(m_xTreeView->get_id(*xFirstSel).toInt64())->GetOutlineLevel(); + SwWrtShell* pSh = GetWrtShell(); + const SwOutlineNodes::size_type nOutlinePos = pSh->GetOutlinePos(MAXLEVEL); + if (nOutlinePos != SwOutlineNodes::npos && pSh->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos) != nSelLevel) + bContentChanged = true; + } + } + // end check if first selected outline level has changed + + pArrType->Init(&bVisibilityChanged); + pArrType->FillMemberList(); + OUString sId(OUString::number(reinterpret_cast(pArrType))); + m_xTreeView->set_id(*xRootEntry, sId); + if (!bContentChanged) + { + const size_t nChildCount = GetChildCount(*xRootEntry); + if (nChildCount != pArrType->GetMemberCount()) + bContentChanged = true; + else + { + std::unique_ptr xEntry(m_xTreeView->make_iterator(xRootEntry.get())); + for (size_t j = 0; j < nChildCount; ++j) + { + m_xTreeView->iter_next(*xEntry); + const SwContent* pCnt = pArrType->GetMember(j); + OUString sSubId(OUString::number(reinterpret_cast(pCnt))); + m_xTreeView->set_id(*xEntry, sSubId); + OUString sEntryText = m_xTreeView->get_text(*xEntry); + if( sEntryText != pCnt->GetName() && + !(sEntryText == m_sSpace && pCnt->GetName().isEmpty())) + bContentChanged = true; + } + } + } + } + } + } + // all content navigation view + else + { + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + bool bEntry = m_xTreeView->get_iter_first(*xEntry); + while (bEntry) + { + bool bNext = true; // at least a next must be + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + SwContentType* pCntType = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()); + const size_t nCntCount = pCntType->GetMemberCount(); + const ContentTypeId nType = pCntType->GetType(); + SwContentType* pArrType = m_aActiveContentArr[nType].get(); + if (!pArrType) + bContentChanged = true; + else + { + pArrType->Init(&bVisibilityChanged); + OUString sId(OUString::number(reinterpret_cast(pArrType))); + m_xTreeView->set_id(*xEntry, sId); + if (m_xTreeView->get_row_expanded(*xEntry)) + { + bool bLevelOrVisibilityChanged = false; + // bLevelOrVisibilityChanged is set if outlines have changed their level + // or if the visibility of objects (frames, sections, tables) has changed + // i.e. in header/footer + pArrType->FillMemberList(&bLevelOrVisibilityChanged); + const size_t nChildCount = GetChildCount(*xEntry); + if (bLevelOrVisibilityChanged) + { + if (nType == ContentTypeId::OUTLINE) + bContentChanged = true; + else + bVisibilityChanged = true; + } + + if(nChildCount != pArrType->GetMemberCount()) + bContentChanged = true; + else + { + for(size_t j = 0; j < nChildCount; ++j) + { + bEntry = m_xTreeView->iter_next(*xEntry); + bNext = false; + const SwContent* pCnt = pArrType->GetMember(j); + OUString sSubId(OUString::number(reinterpret_cast(pCnt))); + m_xTreeView->set_id(*xEntry, sSubId); + OUString sEntryText = m_xTreeView->get_text(*xEntry); + if( sEntryText != pCnt->GetName() && + !(sEntryText == m_sSpace && pCnt->GetName().isEmpty())) + bContentChanged = true; + } + } + } + // not expanded and has children + else if (m_xTreeView->iter_has_child(*xEntry)) + { + // was the entry once opened, then must also the + // invisible records be examined. + // At least the user data must be updated. + bool bLevelOrVisibilityChanged = false; + // bLevelOrVisibilityChanged is set if outlines have changed their level + // or if the visibility of objects (frames, sections, tables) has changed + // i.e. in header/footer + pArrType->FillMemberList(&bLevelOrVisibilityChanged); + bool bRemoveChildren = false; + const size_t nOldChildCount = GetChildCount(*xEntry); + const size_t nNewChildCount = pArrType->GetMemberCount(); + if (nOldChildCount != nNewChildCount) + { + bRemoveChildren = true; + } + else + { + std::unique_ptr 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(OUString::number(reinterpret_cast(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 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; + } + } + // The Root-Entry has to be found now + while (bEntry && (bNext || m_xTreeView->get_iter_depth(*xEntry))) + { + bEntry = m_xTreeView->iter_next(*xEntry); + bNext = false; + } + } + } + + if (!bContentChanged && bVisibilityChanged) + m_aUpdTimer.Start(); + + return bContentChanged || bVisibilityChanged; +} + +void SwContentTree::UpdateLastSelType() +{ + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + if (m_xTreeView->get_selected(xEntry.get())) + { + while (m_xTreeView->get_iter_depth(*xEntry)) + m_xTreeView->iter_parent(*xEntry); + sal_Int64 nId = m_xTreeView->get_id(*xEntry).toInt64(); + if (nId && lcl_IsContentType(*xEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(nId))); + m_nLastSelType = reinterpret_cast(nId)->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()) + { + m_aHiddenContentArr[i].reset(); + } + Display(false); + + GetParentWindow()->UpdateListBox(); +} + +void SwContentTree::SetActiveShell(SwWrtShell* pSh) +{ + bool bClear = m_pActiveShell != pSh; + if (State::ACTIVE == m_eState && bClear) + { + if (m_pActiveShell) + EndListening(*m_pActiveShell->GetView().GetDocShell()); + m_pActiveShell = pSh; + FindActiveTypeAndRemoveUserData(); + clear(); + } + else if (State::CONSTANT == m_eState) + { + if (m_pActiveShell) + EndListening(*m_pActiveShell->GetView().GetDocShell()); + m_pActiveShell = pSh; + m_eState = State::ACTIVE; + bClear = true; + } + // 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()) + { + m_aActiveContentArr[i].reset(); + } + Display(true); + } +} + +void SwContentTree::SetConstantShell(SwWrtShell* pSh) +{ + if (m_pActiveShell) + EndListening(*m_pActiveShell->GetView().GetDocShell()); + m_pActiveShell = pSh; + m_eState = State::CONSTANT; + StartListening(*m_pActiveShell->GetView().GetDocShell()); + FindActiveTypeAndRemoveUserData(); + for(ContentTypeId i : o3tl::enumrange()) + { + m_aActiveContentArr[i].reset(); + } + Display(true); +} + +void SwContentTree::Notify(SfxBroadcaster & rBC, SfxHint const& rHint) +{ + SfxViewEventHint const*const pVEHint(dynamic_cast(&rHint)); + SwXTextView* pDyingShell = nullptr; + if (m_pActiveShell && pVEHint && pVEHint->GetEventName() == "OnViewClosed") + pDyingShell = dynamic_cast(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::DocChanged: + if (!m_bIsInPromoteDemote) + { + m_bViewHasChanged = 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 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; + } +} + +void SwContentTree::ExecCommand(const OString& rCmd, bool bOutlineWithChildren) +{ + const bool bUp = rCmd == "chapterup"; + const bool bUpDown = bUp || rCmd == "chapterdown"; + const bool bLeft = rCmd == "promote"; + const bool bLeftRight = bLeft || rCmd == "demote"; + if (!bUpDown && !bLeftRight) + return; + if (GetWrtShell()->GetView().GetDocShell()->IsReadOnly() || + (State::ACTIVE != m_eState && + (State::CONSTANT != m_eState || m_pActiveShell != GetParentWindow()->GetCreateView()->GetWrtShellPtr()))) + { + return; + } + + m_bIsInPromoteDemote = true; + + SwWrtShell *const pShell = GetWrtShell(); + sal_Int8 nActOutlineLevel = m_nOutlineLevel; + SwOutlineNodes::size_type nActPos = pShell->GetOutlinePos(nActOutlineLevel); + + std::vector selectedOutlineNodes; + std::vector> selected; + + m_xTreeView->selected_foreach([this, pShell, &bLeftRight, &bOutlineWithChildren, &selected, &selectedOutlineNodes](weld::TreeIter& rEntry){ + // it's possible to select the root node too which is a really bad idea + bool bSkip = lcl_IsContentType(rEntry, *m_xTreeView); + // 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 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) + { + bSkip = true; + break; + } + } + } + if (!bSkip) + { + selected.emplace_back(m_xTreeView->make_iterator(&rEntry)); + const SwNodes& rNodes = pShell->GetNodes(); + const size_t nPos = GetAbsPos(rEntry) - 1; + if (nPos < rNodes.GetOutLineNds().size()) + { + SwNode* pNode = rNodes.GetOutLineNds()[ nPos ]; + if (pNode) + { + selectedOutlineNodes.push_back(pNode->GetTextNode()); + } + } + } + return false; + }); + + if (bUpDown && !bUp) + { // to move down, start at the end! + std::reverse(selected.begin(), selected.end()); + } + + SwOutlineNodes::difference_type nDirLast = bUp ? -1 : 1; + bool bStartedAction = false; + for (auto const& pCurrentEntry : selected) + { + assert(pCurrentEntry && lcl_IsContent(*pCurrentEntry, *m_xTreeView)); + if (lcl_IsContent(*pCurrentEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*pCurrentEntry).toInt64()))); + if ((m_bIsRoot && m_nRootType == ContentTypeId::OUTLINE) || + reinterpret_cast(m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetParent()->GetType() + == ContentTypeId::OUTLINE) + { + nActPos = reinterpret_cast(m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetOutlinePos(); + } + } + if (nActPos == SwOutlineNodes::npos || (bUpDown && !pShell->IsOutlineMovable(nActPos))) + { + 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(); + pShell->MakeOutlineSel(nActPos, nActPos, bOutlineWithChildren); + if (bUpDown) + { + const size_t nEntryAbsPos(GetAbsPos(*pCurrentEntry)); + SwOutlineNodes::difference_type nDir = bUp ? -1 : 1; + if (!bOutlineWithChildren && ((nDir == -1 && nActPos > 0) || + (nDir == 1 && nEntryAbsPos < GetEntryCount() - 2))) + { + pShell->MoveOutlinePara( nDir ); + // Set cursor back to the current position + pShell->GotoOutline( nActPos + nDir); + } + else if (bOutlineWithChildren) + { + SwOutlineNodes::size_type nActEndPos = nActPos; + std::unique_ptr xEntry(m_xTreeView->make_iterator(pCurrentEntry.get())); + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*pCurrentEntry).toInt64()))); + const auto nActLevel = reinterpret_cast( + m_xTreeView->get_id(*pCurrentEntry).toInt64())->GetOutlineLevel(); + bool bEntry = m_xTreeView->iter_next(*xEntry); + while (bEntry && lcl_IsContent(*xEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + if (nActLevel >= reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel()) + break; + nActEndPos = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos(); + bEntry = m_xTreeView->iter_next(*xEntry); + } + if (nDir == 1) // move down + { + std::unique_ptr xNextSibling(m_xTreeView->make_iterator(pCurrentEntry.get())); + if (m_xTreeView->iter_next_sibling(*xNextSibling) && m_xTreeView->is_selected(*xNextSibling)) + nDir = nDirLast; + else + { + // If the last entry is to be moved we're done + if (bEntry && lcl_IsContent(*xEntry, *m_xTreeView)) + { + // xEntry now points to the entry following the last + // selected entry. + SwOutlineNodes::size_type nDest = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos(); + // here needs to found the next entry after next. + // The selection must be inserted in front of that. + while (bEntry) + { + bEntry = m_xTreeView->iter_next(*xEntry); + assert(!bEntry || !lcl_IsContent(*xEntry, *m_xTreeView)|| + dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + // nDest++ may only executed if bEntry + if (bEntry) + { + if (!lcl_IsContent(*xEntry, *m_xTreeView)) + break; + else if (nActLevel >= reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel()) + { + // nDest needs adjusted if there are selected entries (including ancestral lineage) + // immediately before the current moved entry. + std::unique_ptr xTmp(m_xTreeView->make_iterator(xEntry.get())); + bool bTmp = m_xTreeView->iter_previous(*xTmp); + while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) && + nActLevel < reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel()) + { + while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) && !m_xTreeView->is_selected(*xTmp) && + nActLevel < reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel()) + { + bTmp = m_xTreeView->iter_parent(*xTmp); + } + if (!bTmp || !m_xTreeView->is_selected(*xTmp)) + break; + bTmp = m_xTreeView->iter_previous(*xTmp); + nDest = reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos(); + } + std::unique_ptr xPrevSibling(m_xTreeView->make_iterator(xEntry.get())); + if (!m_xTreeView->iter_previous_sibling(*xPrevSibling) || !m_xTreeView->is_selected(*xPrevSibling)) + break; + } + else + { + nDest = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos(); + } + } + } + nDirLast = nDir = nDest - nActEndPos; + // If no entry was found that allows insertion before + // it, we just move it to the end. + } + else + nDirLast = nDir = 0; + } + } + else // move up + { + std::unique_ptr xPrevSibling(m_xTreeView->make_iterator(pCurrentEntry.get())); + if (m_xTreeView->iter_previous_sibling(*xPrevSibling) && m_xTreeView->is_selected(*xPrevSibling)) + nDir = nDirLast; + else + { + SwOutlineNodes::size_type nDest = nActPos; + bEntry = true; + m_xTreeView->copy_iterator(*pCurrentEntry, *xEntry); + while (bEntry && nDest) + { + bEntry = m_xTreeView->iter_previous(*xEntry); + assert(!bEntry || !lcl_IsContent(*xEntry, *m_xTreeView) || + dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + if (bEntry && lcl_IsContent(*xEntry, *m_xTreeView)) + { + nDest = reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlinePos(); + } + else + { + nDest = 0; // presumably? + } + if (bEntry) + { + if (!lcl_IsContent(*xEntry, *m_xTreeView)) + break; + else if (nActLevel >= reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetOutlineLevel()) + { + // nDest needs adjusted if there are selected entries immediately + // after the level change. + std::unique_ptr xTmp(m_xTreeView->make_iterator(xEntry.get())); + bool bTmp = m_xTreeView->iter_next(*xTmp); + while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) && + nActLevel < reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel() && + m_xTreeView->is_selected(*xTmp)) + { + nDest = reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos(); + const auto nLevel = reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel(); + // account for selected entries' descendent lineage + bTmp = m_xTreeView->iter_next(*xTmp); + while (bTmp && lcl_IsContent(*xTmp, *m_xTreeView) && + nLevel < reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlineLevel()) + { + nDest = reinterpret_cast(m_xTreeView->get_id(*xTmp).toInt64())->GetOutlinePos(); + bTmp = m_xTreeView->iter_next(*xTmp); + } + } + break; + } + } + } + nDirLast = nDir = nDest - nActPos; + } + } + if (nDir) + { + pShell->MoveOutlinePara( nDir ); + // Set cursor back to the current position + pShell->GotoOutline(nActPos + nDir); + } + } + } + else + { + if (!pShell->IsProtectedOutlinePara()) + pShell->OutlineUpDown(bLeft ? -1 : 1); + } + + pShell->ClearMark(); + 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(); + + // clear all selections to prevent the Display function from trying to reselect selected entries + m_xTreeView->unselect_all(); + Display(true); + + // reselect entries + const SwOutlineNodes::size_type nCurrPos = pShell->GetOutlinePos(MAXLEVEL); + std::unique_ptr xListEntry(m_xTreeView->make_iterator()); + bool bListEntry = m_xTreeView->get_iter_first(*xListEntry); + while ((bListEntry = m_xTreeView->iter_next(*xListEntry)) && lcl_IsContent(*xListEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xListEntry).toInt64()))); + if (reinterpret_cast(m_xTreeView->get_id(*xListEntry).toInt64())->GetOutlinePos() == nCurrPos) + { + std::unique_ptr xParent(m_xTreeView->make_iterator(xListEntry.get())); + if (m_xTreeView->iter_parent(*xParent) && !m_xTreeView->get_row_expanded(*xParent)) + m_xTreeView->expand_row(*xParent); + m_xTreeView->set_cursor(*xListEntry); // unselect all entries, make entry visible, set focus, and select + Select(); + break; + } + } + + if (m_bIsRoot) + { + const SwOutlineNodes& rOutLineNds = pShell->GetNodes().GetOutLineNds(); + for (SwTextNode* pNode : selectedOutlineNodes) + { + SwOutlineNodes::const_iterator aFndIt = rOutLineNds.find(pNode); + if(aFndIt == rOutLineNds.end()) + continue; + const size_t nFndPos = aFndIt - rOutLineNds.begin(); + std::unique_ptr xEntry = GetEntryAtAbsPos(nFndPos + 1); + if (xEntry) + { + m_xTreeView->select(*xEntry); + std::unique_ptr xParent(m_xTreeView->make_iterator(xEntry.get())); + if (m_xTreeView->iter_parent(*xParent) && !m_xTreeView->get_row_expanded(*xParent)) + m_xTreeView->expand_row(*xParent); + } + } + } + } + m_bIsInPromoteDemote = 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(); +} + +/** No idle with focus or while dragging */ +IMPL_LINK_NOARG(SwContentTree, TimerUpdate, Timer *, void) +{ + // 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(); + if(pView && pView->GetWrtShellPtr() && pView->GetWrtShellPtr()->GetWin() && + (pView->GetWrtShellPtr()->GetWin()->HasFocus() || m_bViewHasChanged) && + !IsInDrag() && !pView->GetWrtShellPtr()->ActionPend()) + { + m_bViewHasChanged = false; + m_bIsIdleClear = false; + SwWrtShell* pActShell = pView->GetWrtShellPtr(); + 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); + } + + // track document outline position at cursor + if (m_nOutlineTracking == 3) // no outline tracking + return; + + const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL); // find out where the cursor is + if (nActPos == SwOutlineNodes::npos) + return; + + // only track if selection is already an outline + std::unique_ptr xFirstSelected(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xFirstSelected.get())) + xFirstSelected.reset(); + if (xFirstSelected && lcl_IsContent(*xFirstSelected, *m_xTreeView) && + reinterpret_cast(m_xTreeView->get_id(*xFirstSelected).toInt64())->GetParent()->GetType() != ContentTypeId::OUTLINE) + return; + if (xFirstSelected && lcl_IsContentType(*xFirstSelected, *m_xTreeView) && + reinterpret_cast(m_xTreeView->get_id(*xFirstSelected).toInt64())->GetType() != ContentTypeId::OUTLINE) + return; + + int nSelectedRows = m_xTreeView->count_selected_rows(); + + // find the outline in the tree and select it + m_xTreeView->all_foreach([this, nSelectedRows, nActPos, &xFirstSelected](weld::TreeIter& rEntry){ + bool bRet = false; + + if (lcl_IsContent(rEntry, *m_xTreeView) && + reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64())->GetParent()->GetType() == ContentTypeId::OUTLINE) + { + // might have been scrolled out of view by the user so leave it that way + if (reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos() == nActPos) + { + // only select if not already selected or tree has multiple entries selected + if (nSelectedRows != 1 || m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0) + { + if (m_nOutlineTracking == 2) // focused outline tracking + { + // collapse to children of root node + std::unique_ptr xChildEntry(m_xTreeView->make_iterator()); + if (m_xTreeView->get_iter_first(*xChildEntry) && m_xTreeView->iter_children(*xChildEntry)) + { + do + { + if (reinterpret_cast(m_xTreeView->get_id(*xChildEntry).toInt64())->GetParent()->GetType() == ContentTypeId::OUTLINE) + m_xTreeView->collapse_row(*xChildEntry); + else + break; + } + while (m_xTreeView->iter_next(*xChildEntry)); + } + } + m_xTreeView->set_cursor(rEntry); // unselect all entries, make pEntry visible, and select + Select(); + } + bRet = true; + } + } + else + { + // use of this break assumes outline content type is first in tree + if (lcl_IsContentType(rEntry, *m_xTreeView) && + reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64())->GetType() != ContentTypeId::OUTLINE) + bRet = true; + } + + return bRet; + }); + } + else if (!pView && State::ACTIVE == m_eState && !m_bIsIdleClear) + { + if(m_pActiveShell) + { + SetActiveShell(nullptr); + } + clear(); + m_bIsIdleClear = true; + } +} + +void SwContentTree::MoveOutline(SwOutlineNodes::size_type nTargetPos) +{ + 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 = reinterpret_cast(m_xTreeView->get_id(*source).toInt64())->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, FocusHdl, 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); + else if ((State::ACTIVE == m_eState || (State::CONSTANT == m_eState && pActShell == GetWrtShell())) && + HasContentChanged()) + { + Display(true); + } + } + 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 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 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; + } + } + } + else if(aCode.GetCode() == KEY_DELETE && 0 == aCode.GetModifier()) + { + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + if (m_xTreeView->get_selected(xEntry.get()) && lcl_IsContent(*xEntry, *m_xTreeView)) + { + assert(dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64()))); + if (reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->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 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(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())); + + 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); + const size_t nCount = pPage->GetObjCount(); + 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( size_t i=0; iGetObj(i); + bool bMark = pDrawView->IsObjMarked(pTemp); + switch( pTemp->GetObjIdentifier() ) + { + case OBJ_GRUP: + case OBJ_TEXT: + case OBJ_LINE: + case OBJ_RECT: + case OBJ_CIRC: + case OBJ_SECT: + case OBJ_CARC: + case OBJ_CCUT: + case OBJ_POLY: + case OBJ_PLIN: + case OBJ_PATHLINE: + case OBJ_PATHFILL: + case OBJ_FREELINE: + case OBJ_FREEFILL: + case OBJ_PATHPOLY: + case OBJ_PATHPLIN: + case OBJ_CAPTION: + case OBJ_CUSTOMSHAPE: + if( bMark ) + hasObjectMarked = true; + break; + default: + if ( bMark ) + { + SdrPageView* pPV = pDrawView->GetSdrPageView/*GetPageViewPvNum*/(/*0*/); + if (pPV) + { + pDrawView->MarkObj(pTemp, pPV, true); + } + } + } + //mod end + } + if ( !hasObjectMarked ) + { + SwEditWin& rEditWindow = m_pActiveShell->GetView().GetEditWin(); + vcl::KeyCode tempKeycode( KEY_ESCAPE ); + KeyEvent rKEvt( 0 , tempKeycode ); + static_cast(&rEditWindow)->KeyInput( rKEvt ); + } + } + } + + m_bViewHasChanged = true; + } + } + } + else + { + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + if (m_xTreeView->get_cursor(xEntry.get())) + { + SwContent* pCnt = dynamic_cast(reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())); + 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("promote", !aCode.IsShift()); + else if (aCode.GetCode() == KEY_RIGHT) + ExecCommand("demote", !aCode.IsShift()); + else if (aCode.GetCode() == KEY_UP) + ExecCommand("chapterup", !aCode.IsShift()); + else if (aCode.GetCode() == KEY_DOWN) + ExecCommand("chapterdown", !aCode.IsShift()); + 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 = reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64()); + if (lcl_IsContentType(rEntry, *m_xTreeView)) + { + assert(dynamic_cast(static_cast(pUserData))); + nType = static_cast(pUserData)->GetType(); + } + else + { + assert(dynamic_cast(static_cast(pUserData))); + nType = static_cast(pUserData)->GetParent()->GetType(); + bContent = true; + } + OUString sEntry; + if(bContent) + { + switch( nType ) + { + case ContentTypeId::URLFIELD: + assert(dynamic_cast(static_cast(pUserData))); + sEntry = static_cast(pUserData)->GetURL(); + break; + + case ContentTypeId::POSTIT: + assert(dynamic_cast(static_cast(pUserData))); + sEntry = static_cast(pUserData)->GetName(); + break; + case ContentTypeId::OUTLINE: + assert(dynamic_cast(static_cast(pUserData))); + sEntry = static_cast(pUserData)->GetName(); + break; + case ContentTypeId::GRAPHIC: + assert(dynamic_cast(static_cast(pUserData))); + sEntry = static_cast(pUserData)->GetLink(); + break; + case ContentTypeId::REGION: + { + assert(dynamic_cast(static_cast(pUserData))); + sEntry = static_cast(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, *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; + default: break; + } + if(static_cast(pUserData)->IsInvisible()) + { + if(!sEntry.isEmpty()) + sEntry += ", "; + sEntry += m_sInvisible; + } + } + else + { + const size_t nMemberCount = static_cast(pUserData)->GetMemberCount(); + sEntry = OUString::number(nMemberCount) + " " + + (nMemberCount == 1 + ? static_cast(pUserData)->GetSingleName() + : static_cast(pUserData)->GetName()); + } + + return sEntry; +} + +void SwContentTree::ExecuteContextMenuAction(const OString& rSelectedPopupEntry) +{ + std::unique_ptr xFirst(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xFirst.get())) + xFirst.reset(); + + auto nSelectedPopupEntry = rSelectedPopupEntry.toUInt32(); + switch (nSelectedPopupEntry) + { + case 11: + case 12: + case 13: + nSelectedPopupEntry -= 10; + if(m_nOutlineTracking != nSelectedPopupEntry) + m_nOutlineTracking = 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(nSelectedPopupEntry)); + break; + case 201: + case 202: + case 203: + GetParentWindow()->SetRegionDropMode(static_cast(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 = reinterpret_cast(m_xTreeView->get_id(*xFirst).toInt64()) + ->GetTOXBase(); + m_pActiveShell->SetTOXBaseReadonly(*pBase, !SwEditShell::IsTOXBaseReadonly(*pBase)); + } + break; + case 4: + break; + case 501: + EditEntry(*xFirst, EditEntryMode::DELETE); + 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("chapterup", true); + break; + case 802: + ExecCommand("chapterdown", true); + break; + case 803: + ExecCommand("promote", true); + break; + case 804: + ExecCommand("demote", true); + break; + case 805: + { + m_pActiveShell->KillPams(); + m_pActiveShell->ClearMark(); + m_pActiveShell->EnterAddMode(); + SwContent* pCnt = reinterpret_cast(m_xTreeView->get_id(*xFirst).toInt64()); + const ContentTypeId eTypeId = pCnt->GetParent()->GetType(); + if (eTypeId == ContentTypeId::OUTLINE) + { + m_xTreeView->selected_foreach([this](weld::TreeIter& rEntry){ + m_pActiveShell->SttSelect(); + SwOutlineNodes::size_type nActPos = reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos(); + m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded + m_pActiveShell->EndSelect(); + return false; + }); + } + else if (eTypeId == ContentTypeId::TABLE) + { + m_pActiveShell->GotoTable(pCnt->GetName()); + m_pActiveShell->SelAll(); + } + 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 806: + // Delete outline selections + EditEntry(*xFirst, EditEntryMode::DELETE); + break; + case 900: + { + SwContent* pCnt = reinterpret_cast(m_xTreeView->get_id(*xFirst).toInt64()); + 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() +{ + m_pActiveShell->StartAction(); + m_pActiveShell->EnterAddMode(); + auto nChapters(0); + + m_xTreeView->selected_foreach([this, &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); + } + m_pActiveShell->SttSelect(); + SwOutlineNodes::size_type nActPos = reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos(); + m_pActiveShell->MakeOutlineSel(nActPos, nActPos, !m_xTreeView->get_row_expanded(rEntry), false); // select children if not expanded + 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->SetTextFormatColl(nullptr); + m_pActiveShell->Delete(); + m_pActiveShell->ClearMark(); + m_pActiveShell->EndUndo(); + m_pActiveShell->EndAction(); +} + +void SwContentTree::SetOutlineLevel(sal_uInt8 nSet) +{ + m_nOutlineLevel = nSet; + m_pConfig->SetOutlineLevel( m_nOutlineLevel ); + std::unique_ptr& rpContentT = (State::ACTIVE == m_eState) + ? m_aActiveContentArr[ContentTypeId::OUTLINE] + : m_aHiddenContentArr[ContentTypeId::OUTLINE]; + if(rpContentT) + { + rpContentT->SetOutlineLevel(m_nOutlineLevel); + rpContentT->Init(); + } + Display(State::ACTIVE == m_eState); +} + +// 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) +{ + Select(); +} + +// Here the buttons for moving outlines are en-/disabled. +void SwContentTree::Select() +{ + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xEntry.get())) + return; + + bool bEnable = false; + std::unique_ptr 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) && + reinterpret_cast(m_xTreeView->get_id(*xParentEntry).toInt64())->GetType() == ContentTypeId::OUTLINE)) + { + bEnable = true; + } + } + } + SwNavigationPI* pNavi = GetParentWindow(); + pNavi->m_xContent3ToolBox->set_item_sensitive("chapterup", bEnable); + pNavi->m_xContent3ToolBox->set_item_sensitive("chapterdown", bEnable); + pNavi->m_xContent3ToolBox->set_item_sensitive("promote", bEnable); + pNavi->m_xContent3ToolBox->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 = reinterpret_cast(m_xTreeView->get_id(rEntry).toInt64()); + GotoContent(pCnt); + const ContentTypeId nType = pCnt->GetParent()->GetType(); + sal_uInt16 nSlot = 0; + + 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 : + assert(!m_pActiveShell->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS)); + if(nMode == EditEntryMode::DELETE) + { + IDocumentMarkAccess* const pMarkAccess = m_pActiveShell->getIDocumentMarkAccess(); + pMarkAccess->deleteMark( pMarkAccess->findMark(pCnt->GetName()) ); + } + else if(nMode == EditEntryMode::RENAME) + { + uno::Reference< frame::XModel > xModel = m_pActiveShell->GetView().GetDocShell()->GetBaseModel(); + uno::Reference< text::XBookmarksSupplier > xBkms(xModel, uno::UNO_QUERY); + xNameAccess = xBkms->getBookmarks(); + } + else + nSlot = FN_INSERT_BOOKMARK; + break; + + case ContentTypeId::REGION : + 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: + nSlot = FN_EDIT_FIELD; + break; + + case ContentTypeId::POSTIT: + m_pActiveShell->GetView().GetPostItMgr()->AssureStdModeAtShell(); + if(nMode == EditEntryMode::DELETE) + { + m_pActiveShell->GetView().GetPostItMgr()->SetActiveSidebarWin(nullptr); + m_pActiveShell->DelRight(); + } + else + { + nSlot = FN_POSTIT; + } + break; + case ContentTypeId::INDEX: + { + const SwTOXBase* pBase = static_cast(pCnt)->GetTOXBase(); + switch(nMode) + { + case EditEntryMode::EDIT: + if(pBase) + { + SwPtrItem aPtrItem( FN_INSERT_MULTI_TOX, const_cast(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; + break; + default: break; + } + if(nSlot) + m_pActiveShell->GetView().GetViewFrame()-> + GetDispatcher()->Execute(nSlot, SfxCallMode::ASYNCHRON); + 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 pDlg(pFact->CreateSwRenameXNamedDlg(GetParentWindow()->GetFrameWeld(), 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) + { + m_bViewHasChanged = true; + GetParentWindow()->UpdateListBox(); + TimerUpdate(&m_aUpdTimer); + grab_focus(); + } +} + +void SwContentTree::GotoContent(const SwContent* pCnt) +{ + m_pActiveShell->EnterStdMode(); + + bool bSel = false; + switch(pCnt->GetParent()->GetType()) + { + case ContentTypeId::OUTLINE : + { + m_pActiveShell->GotoOutline(static_cast(pCnt)->GetOutlinePos()); + } + break; + case ContentTypeId::TABLE : + { + m_pActiveShell->GotoTable(pCnt->GetName()); + } + break; + case ContentTypeId::FRAME : + case ContentTypeId::GRAPHIC : + case ContentTypeId::OLE : + { + if(m_pActiveShell->GotoFly(pCnt->GetName())) + bSel = true; + } + break; + case ContentTypeId::BOOKMARK: + { + m_pActiveShell->GotoMark(pCnt->GetName()); + } + break; + case ContentTypeId::REGION : + { + m_pActiveShell->GotoRegion(pCnt->GetName()); + } + break; + case ContentTypeId::URLFIELD: + { + if(m_pActiveShell->GotoINetAttr( + *static_cast(pCnt)->GetINetAttr() )) + { + m_pActiveShell->Right( CRSR_SKIP_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->GetView().GetPostItMgr()->AssureStdModeAtShell(); + m_pActiveShell->GotoFormatField(*static_cast(pCnt)->GetPostIt()); + break; + case ContentTypeId::DRAWOBJECT: + { + SwPosition aPos = *m_pActiveShell->GetCursor()->GetPoint(); + SdrView* pDrawView = m_pActiveShell->GetDrawView(); + if (pDrawView) + { + pDrawView->SdrEndTextEdit(); + pDrawView->UnmarkAll(); + SwDrawModel* _pModel = m_pActiveShell->getIDocumentDrawModelAccess().GetDrawModel(); + SdrPage* pPage = _pModel->GetPage(0); + const size_t nCount = pPage->GetObjCount(); + for( size_t i=0; iGetObj(i); + if (pTemp->GetName() == pCnt->GetName()) + { + SdrPageView* pPV = pDrawView->GetSdrPageView(); + if( pPV ) + { + pDrawView->MarkObj( pTemp, pPV ); + } + } + } + m_pActiveShell->GetNavigationMgr().addEntry(aPos); + m_pActiveShell->EnterStdMode(); + bSel = true; + } + } + break; + default: break; + } + if(bSel) + { + m_pActiveShell->HideCursor(); + m_pActiveShell->EnterSelFrameMode(); + } + SwView& rView = m_pActiveShell->GetView(); + rView.StopShellTimer(); + rView.GetPostItMgr()->SetActiveSidebarWin(nullptr); + rView.GetEditWin().GrabFocus(); + + // force scroll to cursor position when navigating to inactive document + if(!bSel) + { + Point rPoint = m_pActiveShell->GetCursorDocPos(); + rPoint.setX(0); + rView.SetVisArea(rPoint); + } +} + +// Now even the matching text::Bookmark +NaviContentBookmark::NaviContentBookmark() + : + nDocSh(0), + nDefDrag( RegionMode::NONE ) +{ +} + +NaviContentBookmark::NaviContentBookmark( const OUString &rUrl, + const OUString& rDesc, + RegionMode nDragType, + const SwDocShell* pDocSh ) : + aUrl( rUrl ), + aDescr(rDesc), + nDocSh(reinterpret_cast(pDocSh)), + nDefDrag( nDragType ) +{ +} + +void NaviContentBookmark::Copy( TransferDataContainer& rData ) const +{ + rtl_TextEncoding eSysCSet = osl_getThreadTextEncoding(); + + OString sStrBuf(OUStringToOString(aUrl, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) + + OUStringToOString(aDescr, eSysCSet) + OStringChar(NAVI_BOOKMARK_DELIM) + + OString::number(static_cast(nDefDrag)) + OStringChar(NAVI_BOOKMARK_DELIM) + + OString::number(nDocSh)); + rData.CopyByteString(SotClipboardFormatId::SONLK, sStrBuf); +} + +bool NaviContentBookmark::Paste( TransferableDataHelper& rData ) +{ + OUString sStr; + bool bRet = rData.GetString( SotClipboardFormatId::SONLK, sStr ); + if( bRet ) + { + sal_Int32 nPos = 0; + aUrl = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ); + aDescr = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ); + nDefDrag= static_cast( sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ).toInt32() ); + nDocSh = sStr.getToken(0, NAVI_BOOKMARK_DELIM, nPos ).toInt32(); + } + return bRet; +} + +SwNavigationPI* SwContentTree::GetParentWindow() +{ + return m_xDialog; +} + +/* 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 000000000..3261050f3 --- /dev/null +++ b/sw/source/uibase/utlui/glbltree.cxx @@ -0,0 +1,1088 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::uno; + +#define GLOBAL_UPDATE_TIMEOUT 2000 + +const SfxObjectShell* SwGlobalTree::pShowShell = nullptr; + +namespace { + +class SwGlobalFrameListener_Impl : public SfxListener +{ + bool bValid; +public: + explicit SwGlobalFrameListener_Impl(SfxViewFrame& rFrame) + : bValid(true) + { + StartListening(rFrame); + } + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + + bool IsValid() const {return bValid;} +}; + +} + +void SwGlobalFrameListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + if( rHint.GetId() == SfxHintId::Dying) + 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 +}; + +} + +static const char* 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 xTreeView, SwNavigationPI* pDialog) + : m_xTreeView(std::move(xTreeView)) + , m_aDropTargetHelper(*this) + , m_xDialog(pDialog) + , m_pActiveShell(nullptr) +{ + Size aSize(m_xDialog->LogicToPixel(Size(110, 112), MapMode(MapUnit::MapAppFont)));; + m_xTreeView->set_size_request(aSize.Width(), aSize.Height()); + + 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(); + m_xDialog.clear(); +} + +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 xDropEntry(rWidget.make_iterator()); + if (!rWidget.get_dest_row_at_pos(rEvt.maPosPixel, xDropEntry.get())) + 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 ? + reinterpret_cast(rWidget.get_id(*xDropEntry).toInt64()) : + nullptr; + if( aData.HasFormat( SotClipboardFormatId::FILE_LIST )) + { + nRet = rEvt.mnAction; + std::unique_ptr pTempContents(new SwGlblDocContents); + 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) + { + m_rTreeView.GetActiveWrtShell()->GetGlobalDocContent(*pTempContents); + // If the file was successfully inserted, + // then the next content must also be fetched. + if(nEntryCount < pTempContents->size()) + { + nEntryCount++; + nAbsContPos++; + pCnt = (*pTempContents)[ 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); + + 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 xBuilder(Application::CreateBuilder(m_xTreeView.get(), "modules/swriter/ui/mastercontextmenu.ui")); + std::unique_ptr xPopup = xBuilder->weld_menu("navmenu"); + + const MenuEnableFlags nEnableFlags = GetEnableFlags(); + + xPopup->set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel)); + + xPopup->set_sensitive("editlink", bool(nEnableFlags & MenuEnableFlags::EditLink)); + + //disabling if applicable + xPopup->set_sensitive("insertindex", bool(nEnableFlags & MenuEnableFlags::InsertIdx )); + xPopup->set_sensitive("insertfile", bool(nEnableFlags & MenuEnableFlags::InsertFile)); + xPopup->set_sensitive("insertnewfile", bool(nEnableFlags & MenuEnableFlags::InsertFile)); + xPopup->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)); + + OString sCommand = xPopup->popup_at_rect(m_xTreeView.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))); + if (!sCommand.isEmpty()) + ExecuteContextMenuAction(sCommand); + } + return bPop; +} + +void SwGlobalTree::TbxMenuHdl(const OString& rCommand, weld::Menu& rMenu) +{ + const MenuEnableFlags nEnableFlags = GetEnableFlags(); + if (rCommand == "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 == "update") + { + rMenu.set_sensitive("updatesel", bool(nEnableFlags & MenuEnableFlags::UpdateSel)); + } +} + +MenuEnableFlags SwGlobalTree::GetEnableFlags() const +{ + std::unique_ptr xEntry(m_xTreeView->make_iterator()); + bool bEntry = m_xTreeView->get_selected(xEntry.get()); + + sal_uLong nSelCount = m_xTreeView->count_selected_rows(); + size_t nEntryCount = m_xTreeView->n_children(); + std::unique_ptr 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 && reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->GetType() != GLBLDOC_UNKNOWN && + (!bPrevEntry || reinterpret_cast(m_xTreeView->get_id(*xPrevEntry).toInt64())->GetType() != GLBLDOC_UNKNOWN)) + nRet |= MenuEnableFlags::InsertText; + if (bEntry && GLBLDOC_SECTION == reinterpret_cast(m_xTreeView->get_id(*xEntry).toInt64())->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 = reinterpret_cast(m_xTreeView->get_id(rIter).toInt64()); + 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(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 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(OUString::number(reinterpret_cast(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(); + if (!m_pSwGlblDocContents) + Update( false ); + + int nSelEntry = -1; + for (size_t i = 0; i < nCount; ++i) + { + const SwGlblDocContent* pCont = (*m_pSwGlblDocContents)[i].get(); + + OUString sId(OUString::number(reinterpret_cast(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 ) + { + m_pDocInserter.reset(new ::sfx2::DocumentInserter(GetParentWindow()->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 ); + aFileNames.getArray()[0] = aFileName.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + 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(const OString& rSelectedPopupEntry) +{ + bool bUpdateHard = false; + + int nEntry = m_xTreeView->get_selected_index(); + SwGlblDocContent* pCont = nEntry != -1 ? reinterpret_cast(m_xTreeView->get_id(nEntry).toInt64()) : 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::unique_ptr pContCopy; + if(pCont) + pContCopy.reset(new SwGlblDocContent(pCont->GetDocPos())); + SfxDispatcher& rDispatch = *m_pActiveShell->GetView().GetViewFrame()->GetDispatcher(); + sal_uInt16 nSlot = 0; + if (rSelectedPopupEntry == "updatesel") + { + // Two passes: first update the areas, then the directories. + m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){ + SwGlblDocContent* pContent = reinterpret_cast(m_xTreeView->get_id(rSelEntry).toInt64()); + if (GLBLDOC_SECTION == pContent->GetType() && + pContent->GetSection()->IsConnected()) + { + const_cast(pContent->GetSection())->UpdateNow(); + } + return false; + }); + m_xTreeView->selected_foreach([this](weld::TreeIter& rSelEntry){ + SwGlblDocContent* pContent = reinterpret_cast(m_xTreeView->get_id(rSelEntry).toInt64()); + if (GLBLDOC_TOXBASE == pContent->GetType()) + m_pActiveShell->UpdateTableOf(*pContent->GetTOX()); + return false; + }); + + bUpdateHard = true; + } + else if (rSelectedPopupEntry == "updateindex") + { + nSlot = FN_UPDATE_TOX; + bUpdateHard = true; + } + else if (rSelectedPopupEntry == "updatelinks" || rSelectedPopupEntry == "updateall") + { + m_pActiveShell->GetLinkManager().UpdateAllLinks(true, false, nullptr); + if (rSelectedPopupEntry == "updateall") + nSlot = FN_UPDATE_TOX; + pCont = nullptr; + bUpdateHard = true; + } + else if (rSelectedPopupEntry == "edit") + { + OSL_ENSURE(pCont, "edit without entry ? " ); + if (pCont) + { + EditContent(pCont); + } + } + else if (rSelectedPopupEntry == "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 == "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 aRows = m_xTreeView->get_selected_rows(); + std::sort(aRows.begin(), aRows.end()); + + std::unique_ptr 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 == "insertindex") + { + if(pContCopy) + { + SfxItemSet aSet( + m_pActiveShell->GetView().GetPool(), + svl::Items< + 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>{}); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateMultiTOXTabDialog( + m_xDialog->GetFrameWeld(), 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( *pContCopy, *pToInsert ); + } + pCont = nullptr; + } + } + else if (rSelectedPopupEntry == "insertfile") + { + m_pDocContent = std::move(pContCopy); + InsertRegion( m_pDocContent.get() ); + pCont = nullptr; + } + else if (rSelectedPopupEntry == "insertnewfile") + { + SfxViewFrame* pGlobFrame = m_pActiveShell->GetView().GetViewFrame(); + SwGlobalFrameListener_Impl aFrameListener(*pGlobFrame); + + // Creating a new doc + SfxStringItem aFactory(SID_NEWDOCDIRECT, + SwDocShell::Factory().GetFilterContainer()->GetName()); + + const SfxFrameItem* pItem = static_cast( + rDispatch.ExecuteList(SID_NEWDOCDIRECT, + SfxCallMode::SYNCHRON, { &aFactory })); + + // save at + SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr; + SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr; + if (pViewFrame) + { + const SfxBoolItem* pBool = static_cast( + pViewFrame->GetDispatcher()->Execute( + SID_SAVEASDOC, SfxCallMode::SYNCHRON )); + 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()) + { + pGlobFrame->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 ? reinterpret_cast(m_xTreeView->get_id(nEntry).toInt64()) : 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 == "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 == "update") + pCont = nullptr; + + if (pCont) + GotoContent(pCont); + if (nSlot) + rDispatch.Execute(nSlot); + if (Update(bUpdateHard)) + Display(); +} + +IMPL_LINK_NOARG(SwGlobalTree, Timeout, Timer *, void) +{ + if (!m_xTreeView->has_focus() && Update(false)) + Display(); +} + +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(); +} + +void SwGlobalTree::HideTree() +{ + m_aUpdateTimer.Stop(); + m_xTreeView->hide(); +} + +void SwGlobalTree::ExecCommand(const OString &rCmd) +{ + int nEntry = m_xTreeView->get_selected_index(); + if (nEntry == -1) + return; + if (rCmd == "edit") + { + const SwGlblDocContent* pCont = reinterpret_cast( + m_xTreeView->get_id(nEntry).toInt64()); + EditContent(pCont); + } + else + { + if (m_xTreeView->count_selected_rows() == 1) + { + bool bMove = false; + sal_uLong nSource = nEntry; + sal_uLong nDest = nSource; + if (rCmd == "movedown") + { + size_t nEntryCount = m_xTreeView->n_children(); + bMove = nEntryCount > nSource + 1; + nDest+= 2; + } + else if (rCmd == "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(!m_pSwGlblDocContents) + { + m_pSwGlblDocContents.reset(new SwGlblDocContents); + bRet = true; + m_pActiveShell->GetGlobalDocContent(*m_pSwGlblDocContents); + } + else + { + bool bCopy = false; + std::unique_ptr pTempContents(new SwGlblDocContents); + m_pActiveShell->GetGlobalDocContent(*pTempContents); + size_t nChildren = m_xTreeView->n_children(); + if (pTempContents->size() != m_pSwGlblDocContents->size() || + pTempContents->size() != nChildren) + { + bRet = true; + bCopy = true; + } + else + { + for(size_t i = 0; i < pTempContents->size() && !bCopy; i++) + { + SwGlblDocContent* pLeft = (*pTempContents)[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( *pTempContents ); + 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 = reinterpret_cast(m_xTreeView->get_id(nEntry).toInt64()); + if (pCont->GetType() == GLBLDOC_SECTION) + OpenDoc(pCont); + else + { + GotoContent(pCont); + m_pActiveShell->GetView().GetEditWin().GrabFocus(); + } + return false; +} + +SwNavigationPI* SwGlobalTree::GetParentWindow() +{ + return m_xDialog; +} + +IMPL_STATIC_LINK_NOARG(SwGlobalTree, ShowFrameHdl, void*, void) +{ + SfxViewFrame* pFirst = pShowShell ? SfxViewFrame::GetFirst(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() ) + { + Sequence< OUString >aFileNames( aMedList.size() ); + OUString* pFileNames = aFileNames.getArray(); + sal_Int32 nPos = 0; + for (const std::unique_ptr& pMed : aMedList) + { + OUString sFileName = pMed->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) + + OUStringChar(sfx2::cTokenSeparator) + + pMed->GetFilter()->GetFilterName() + + OUStringChar(sfx2::cTokenSeparator); + pFileNames[nPos++] = sFileName; + } + InsertRegion( m_pDocContent.get(), aFileNames ); + m_pDocContent.reset(); + } +} + +/* 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 000000000..b58335850 --- /dev/null +++ b/sw/source/uibase/utlui/gloslst.cxx @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 m_xOk; + std::unique_ptr 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() : + bFilled(false) +{ + SvtPathOptions aPathOpt; + 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(const OUString& rLongName, + OUString& rShortName, OUString& rGroupName ) +{ + if(!bFilled) + Update(); + + std::vector aTripleStrings; + + size_t nCount = aGroupArr.size(); + for(size_t i = 0; i < nCount; i++ ) + { + AutoTextGroup* pGroup = 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(); + SwGlossDecideDlg aDlg(pView ? pView->GetFrameWeld() : nullptr); + 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(!bFilled) + Update(); + return aGroupArr.size(); +} + +OUString SwGlossaryList::GetGroupName(size_t nPos) +{ + OSL_ENSURE(aGroupArr.size() > nPos, "group not available"); + if(nPos < aGroupArr.size()) + { + AutoTextGroup* pGroup = aGroupArr[nPos].get(); + OUString sRet = pGroup->sName; + return sRet; + } + return OUString(); +} + +OUString SwGlossaryList::GetGroupTitle(size_t nPos) +{ + OSL_ENSURE(aGroupArr.size() > nPos, "group not available"); + if(nPos < aGroupArr.size()) + { + AutoTextGroup* pGroup = aGroupArr[nPos].get(); + return pGroup->sTitle; + } + return OUString(); +} + +sal_uInt16 SwGlossaryList::GetBlockCount(size_t nGroup) +{ + OSL_ENSURE(aGroupArr.size() > nGroup, "group not available"); + if(nGroup < aGroupArr.size()) + { + AutoTextGroup* pGroup = aGroupArr[nGroup].get(); + return pGroup->nCount; + } + return 0; +} + +OUString SwGlossaryList::GetBlockLongName(size_t nGroup, sal_uInt16 nBlock) +{ + OSL_ENSURE(aGroupArr.size() > nGroup, "group not available"); + if(nGroup < aGroupArr.size()) + { + AutoTextGroup* pGroup = aGroupArr[nGroup].get(); + return pGroup->sLongNames.getToken(nBlock, STRING_DELIM); + } + return OUString(); +} + +OUString SwGlossaryList::GetBlockShortName(size_t nGroup, sal_uInt16 nBlock) +{ + OSL_ENSURE(aGroupArr.size() > nGroup, "group not available"); + if(nGroup < aGroupArr.size()) + { + AutoTextGroup* pGroup = 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 != sPath) + { + sPath = sTemp; + bFilled = false; + ClearGroups(); + } + SwGlossaries* pGlossaries = ::GetGlossaries(); + const std::vector & rPathArr = pGlossaries->GetPathArray(); + const OUString sExt( SwGlossaries::GetExtension() ); + if(!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( + sGrpName.getToken(1, GLOS_DELIM).toInt32()); + if( nPath < rPathArr.size() ) + { + std::unique_ptr pGroup(new AutoTextGroup); + pGroup->sName = sGrpName; + + FillGroup(pGroup.get(), pGlossaries); + OUString sName = rPathArr[nPath] + "/" + + pGroup->sName.getToken(0, GLOS_DELIM) + sExt; + FStatHelper::GetModifiedDateTimeOfFile( sName, + &pGroup->aDateModified, + &pGroup->aDateModified ); + + aGroupArr.insert( aGroupArr.begin(), std::move(pGroup) ); + } + } + bFilled = true; + } + else + { + for( size_t nPath = 0; nPath < rPathArr.size(); nPath++ ) + { + std::vector aFoundGroupNames; + std::vector aFiles; + std::vector 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( static_cast(nPath) ); + AutoTextGroup* pFound = FindGroup( sName ); + if( !pFound ) + { + pFound = new AutoTextGroup; + pFound->sName = sName; + FillGroup( pFound, pGlossaries ); + pFound->aDateModified = rDT; + + aGroupArr.push_back(std::unique_ptr(pFound)); + } + else if( pFound->aDateModified < rDT ) + { + FillGroup(pFound, pGlossaries); + pFound->aDateModified = rDT; + } + } + + for( size_t i = aGroupArr.size(); i>0; ) + { + --i; + // maybe remove deleted groups + AutoTextGroup* pGroup = aGroupArr[i].get(); + const size_t nGroupPath = static_cast( + pGroup->sName.getToken( 1, GLOS_DELIM).toInt32()); + // Only the groups will be checked which are registered + // for the current subpath. + if( nGroupPath == nPath ) + { + OUString sCompareGroup = pGroup->sName.getToken(0, GLOS_DELIM); + bool bFound = std::any_of(aFoundGroupNames.begin(), aFoundGroupNames.end(), + [&sCompareGroup](const OUString& rGroupName) { return sCompareGroup == rGroupName; }); + + if(!bFound) + { + aGroupArr.erase(aGroupArr.begin() + i); + } + } + } + } + } +} + +void SwGlossaryList::Invoke() +{ + // Only update automatically if a SwView has the focus. + if(::GetActiveView()) + Update(); +} + +AutoTextGroup* SwGlossaryList::FindGroup(const OUString& rGroupName) +{ + for(const auto & pRet : aGroupArr) + { + if(pRet->sName == rGroupName) + return pRet.get(); + } + return nullptr; +} + +void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries) +{ + std::unique_ptr 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& rBeginCandidates, + std::vector>& rLongNames) +{ + if(!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> 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 : 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> 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& s1, const std::pair& s2) { + return s1.first.equalsIgnoreAsciiCase(s2.first); + }); + if (const auto nCount = std::min(std::distance(aAllResults.begin(), it), FIND_MAX_GLOS)) + { + rLongNames.insert(rLongNames.end(), aAllResults.begin(), aAllResults.begin() + nCount); + } +} + +void SwGlossaryList::ClearGroups() +{ + aGroupArr.clear(); + 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 000000000..63e7c424c --- /dev/null +++ b/sw/source/uibase/utlui/gotodlg.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +SwGotoPageDlg::SwGotoPageDlg(weld::Window* pParent, SfxBindings* _pBindings) + : GenericDialogController(pParent, "modules/swriter/ui/gotopagedialog.ui", "GotoPageDialog") + , m_pCreateView(nullptr) + , m_rBindings(_pBindings) + , mnMaxPageCnt(1) + , mxMtrPageCtrl(m_xBuilder->weld_entry("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()) + { + int page_value = mxMtrPageCtrl->get_text().toInt32(); + + if (page_value <= 0) + mxMtrPageCtrl->set_text(OUString::number(1)); + else if(page_value > mnMaxPageCnt) + mxMtrPageCtrl->set_text(OUString::number(mnMaxPageCnt)); + + 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(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_text(OUString::number(1)); + if (pSh) + { + const sal_uInt16 nPageCnt = pSh->GetPageCnt(); + sal_uInt16 nPhyPage, nVirPage; + pSh->GetPageNum(nPhyPage, nVirPage); + mxMtrPageCtrl->set_text(OUString::number(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 000000000..f9567ec4a --- /dev/null +++ b/sw/source/uibase/utlui/initui.cxx @@ -0,0 +1,289 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Global Pointer + +static std::unique_ptr 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* pAuthFieldNameList = nullptr; +std::vector* 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(); +} + +static const char* 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 (size_t i = 0; i < SAL_N_ELEMENTS(FLD_DOCINFO_ARY); ++i) + aDocInfoLst.push_back(SwResId(FLD_DOCINFO_ARY[i])); +} + +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(!pAutoFormatNameLst); + pAutoFormatNameLst.reset( new std::vector ); + pAutoFormatNameLst->reserve(STR_AUTOFMTREDL_END); + + 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()); + } + pAutoFormatNameLst->push_back(p); + } +} + +namespace +{ + const char* 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 + }; +} + +OUString const & SwAuthorityFieldType::GetAuthFieldName(ToxAuthorityField eType) +{ + if(!pAuthFieldNameList) + { + pAuthFieldNameList = new std::vector; + 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)]; +} + +static const char* 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; + 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)]; +} + +/* 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 000000000..f1b4f3983 --- /dev/null +++ b/sw/source/uibase/utlui/navicfg.cxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include + +using namespace ::utl; +using namespace ::com::sun::star::uno; + +Sequence SwNavigationConfig::GetPropertyNames() +{ + return css::uno::Sequence{ + OUString("RootType"), + OUString("SelectedPosition"), + OUString("OutlineLevel"), + OUString("InsertMode"), + OUString("ActiveBlock"), + OUString("ShowListBox"), + OUString("GlobalDocMode")}; +} + +SwNavigationConfig::SwNavigationConfig() : + utl::ConfigItem("Office.Writer/Navigator"), + nRootType(ContentTypeId::UNKNOWN), + nSelectedPos(0), + nOutlineLevel(MAXLEVEL), + nRegionMode(RegionMode::NONE), + nActiveBlock(0), + bIsSmall(false), + bIsGlobalActive(true) +{ + Sequence aNames = GetPropertyNames(); + Sequence 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: + { + 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); + } + nRootType = static_cast(nTmp); + } + break; + } + case 1: pValues[nProp] >>= nSelectedPos; break; + case 2: pValues[nProp] >>= nOutlineLevel; break; + case 3: + { + sal_uInt16 nTmp; + if (pValues[nProp] >>= nTmp) + nRegionMode = static_cast(nTmp); + break; + } + case 4: pValues[nProp] >>= nActiveBlock; break; + case 5: bIsSmall = *o3tl::doAccess(pValues[nProp]); break; + case 6: bIsGlobalActive = *o3tl::doAccess(pValues[nProp]); break; + } + } + } + } +} + +SwNavigationConfig::~SwNavigationConfig() +{ +} + +void SwNavigationConfig::ImplCommit() +{ + Sequence aNames = GetPropertyNames(); + Sequence aValues(aNames.getLength()); + Any* pValues = aValues.getArray(); + + for(int nProp = 0; nProp < aNames.getLength(); nProp++) + { + switch(nProp) + { + case 0: pValues[nProp] <<= static_cast(nRootType); break; + case 1: pValues[nProp] <<= nSelectedPos; break; + case 2: pValues[nProp] <<= nOutlineLevel; break; + case 3: pValues[nProp] <<= static_cast(nRegionMode); break; + case 4: pValues[nProp] <<= nActiveBlock; break; + case 5: pValues[nProp] <<= bIsSmall; break; + case 6: pValues[nProp] <<= bIsGlobalActive; break; + } + } + PutProperties(aNames, aValues); +} + +void SwNavigationConfig::Notify( const css::uno::Sequence< OUString >& ) {} + +/* 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 000000000..577aba8fc --- /dev/null +++ b/sw/source/uibase/utlui/navipi.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; + +//! soon obsolete ! +std::unique_ptr SwNavigationChild::CreateImpl( vcl::Window *pParent, + SfxBindings *pBindings, SfxChildWinInfo* /*pInfo*/ ) +{ + return std::make_unique(pParent, + /* cast is safe here! */static_cast< sal_uInt16 >(SwView::GetInterfaceId()), + pBindings); +} +void SwNavigationChild::RegisterChildWindowContext(SfxModule* pMod) +{ + auto pFact = std::make_unique( + SwNavigationChild::CreateImpl, + /* cast is safe here! */static_cast< sal_uInt16 >(SwView::GetInterfaceId()) ); + SfxChildWindowContext::RegisterChildWindowContext(pMod, SID_NAVIGATOR, std::move(pFact)); +} + + +// 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 )) + { + + 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()); + } +} + +// 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; + } +} + +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 OString&, 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") + { + rSh.GetView().GetViewFrame()->GetDispatcher()->Execute(FN_SCROLL_PREV, SfxCallMode::ASYNCHRON); + } + else if (rCommand == ".uno:ScrollToNext") + { + rSh.GetView().GetViewFrame()->GetDispatcher()->Execute(FN_SCROLL_NEXT, SfxCallMode::ASYNCHRON); + } + else if (rCommand == "root") + { + m_xContentTree->ToggleToRoot(); + } + else if (rCommand == "listbox") + { + if (SfxChildWindowContext::GetFloatingWindow(GetParent())) + { + 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_xContent3ToolBox->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_xContent3ToolBox->set_menu_item_active("dragmode", !m_xContent3ToolBox->get_menu_item_active("dragmode")); + else if (rCommand == "headings") + m_xContent2ToolBox->set_menu_item_active("headings", !m_xContent2ToolBox->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 OString&, 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, ToolBox3DropdownClickHdl, const OString&, rCommand, void) +{ + if (!m_xContent3ToolBox->get_menu_item_active(rCommand)) + return; + + if (rCommand == "dragmode") + { + 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 OString&, 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 OString&, rIdent, void) +{ + m_xGlobalTree->ExecuteContextMenuAction(rIdent); +} + +IMPL_LINK(SwNavigationPI, ToolBox2DropdownClickHdl, const OString&, rCommand, void) +{ + if (!m_xContent2ToolBox->get_menu_item_active(rCommand)) + return; + + if (rCommand == "headings") + m_xHeadingsMenu->set_active(OString::number(m_xContentTree->GetOutlineLevel()), true); +} + +FactoryFunction SwNavigationPI::GetUITestFactory() const +{ + return SwNavigationPIUIObject::create; +} + +// 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; + + SwWrtShell &rSh = m_pCreateView->GetWrtShell(); + sal_uInt16 nNewPage = m_xEdit->get_value(); + + rSh.GotoPage(nNewPage, true); + m_pCreateView->GetViewFrame()->GetBindings().Invalidate(FN_STAT_PAGE); + + return true; +} + +void SwNavigationPI::ZoomOut() +{ + if (!IsZoomedIn()) + return; + SfxNavigator* pNav = dynamic_cast(GetParent()); + 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(); + } + + Size aOptimalSize(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_xContent3ToolBox->set_item_active("listbox", true); +} + +void SwNavigationPI::ZoomIn() +{ + if (IsZoomedIn()) + return; + SfxNavigator* pNav = dynamic_cast(GetParent()); + if (!pNav) + return; + + m_aExpandedSize = GetSizePixel(); + + m_xContentBox->hide(); + m_xContentTree->HideTree(); + m_xGlobalBox->hide(); + m_xGlobalTree->HideTree(); + m_xDocListBox->hide(); + m_bIsZoomedIn = true; + + Size aOptimalSize(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_xContent3ToolBox->set_item_active("listbox", false); +} + +namespace { + +enum StatusIndex +{ + IDX_STR_HIDDEN = 0, + IDX_STR_ACTIVE = 1, + IDX_STR_INACTIVE = 2 +}; + +} + +VclPtr SwNavigationPI::Create(vcl::Window* pParent, + const css::uno::Reference& 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 VclPtr::Create(pParent, rxFrame, pBindings); +} + +SwNavigationPI::SwNavigationPI(vcl::Window* pParent, + const css::uno::Reference& rxFrame, + SfxBindings* _pBindings) + : PanelLayout(pParent, "NavigatorPanel", "modules/swriter/ui/navigatorpanel.ui", rxFrame) + , 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_xContent1Dispatch(new ToolbarUnoDispatcher(*m_xContent1ToolBox, *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_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) +{ + set_id("NavigatorPanelParent"); // for uitest/writer_tests5/tdf114724.py + + 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_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->set_help_id("modules/swriter/ui/navigatorpanel/numericfield"); + + if (!IsGlobalDoc()) + { + m_xContent1ToolBox->set_item_visible("contenttoggle", false); + } + + const char* REGIONNAME_ARY[] = + { + STR_HYPERLINK, + STR_LINK_REGION, + STR_COPY_REGION + }; + + const char* 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(RegionMode::EMBEDDED) + 1, "### unexpected size!"); + + for (sal_uInt16 i = 0; i <= static_cast(RegionMode::EMBEDDED); ++i) + { + m_aStatusArr[i] = SwResId(REGIONMODE_ARY[i]); + } + + m_aStatusArr[3] = SwResId(STR_ACTIVE_VIEW); + + bool bFloatingNavigator = SfxChildWindowContext::GetFloatingWindow(GetParent()) != nullptr; + + m_xContentTree->set_selection_mode(SelectionMode::Single); + m_xContentTree->ShowTree(); + m_xContent3ToolBox->set_item_active("listbox", true); + m_xContent3ToolBox->set_item_sensitive("listbox", bFloatingNavigator); + +// TreeListBox for global document + m_xGlobalTree->set_selection_mode(SelectionMode::Multiple); + +// Handler + Link aLk = LINK(this, SwNavigationPI, ToolBoxSelectHdl); + m_xContent1ToolBox->connect_clicked(aLk); + m_xContent2ToolBox->connect_clicked(aLk); + m_xContent3ToolBox->connect_clicked(aLk); + m_xGlobalToolBox->connect_clicked(aLk); + m_xDocListBox->connect_changed(LINK(this, SwNavigationPI, DocListBoxSelectHdl)); + m_xContent2ToolBox->set_item_menu("headings", m_xHeadingsMenu.get()); + m_xHeadingsMenu->connect_activate(LINK(this, SwNavigationPI, HeadingsMenuSelectHdl)); + m_xContent2ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox2DropdownClickHdl)); + m_xContent3ToolBox->set_item_menu("dragmode", m_xDragModeMenu.get()); + m_xDragModeMenu->connect_activate(LINK(this, SwNavigationPI, DropModeMenuSelectHdl)); + m_xContent3ToolBox->connect_menu_toggled(LINK(this, SwNavigationPI, ToolBox3DropdownClickHdl)); + 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); + +// set toolbar of both modes to widest of each + m_xGlobalToolBox->set_size_request(m_xContent1ToolBox->get_preferred_size().Width(), -1); + + StartListening(*SfxGetpApp()); + + if(IsGlobalDoc()) + { + SwView *pActView = GetCreateView(); + 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 = GetOptimalSize(); +} + +SwNavigationPI::~SwNavigationPI() +{ + disposeOnce(); +} + +void SwNavigationPI::dispose() +{ + if (IsGlobalDoc() && !IsGlobalMode()) + { + SwView *pView = GetCreateView(); + SwWrtShell &rSh = pView->GetWrtShell(); + if (!rSh.IsAllProtect()) + pView->GetDocShell()->SetReadOnlyUI(false); + } + + EndListening(*SfxGetpApp()); + + if (m_pxObjectShell) + { + if (m_pxObjectShell->Is()) + (*m_pxObjectShell)->DoClose(); + m_pxObjectShell.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_xContent1Dispatch.reset(); + m_xContent1ToolBox.reset(); + m_xContent2ToolBox.reset(); + m_xContent3ToolBox.reset(); + + m_aPageChgIdle.Stop(); + + m_aDocFullName.dispose(); + m_aPageStats.dispose(); + + PanelLayout::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) + { + SwView *pActView = GetCreateView(); + if(pActView) + { + SwWrtShell &rSh = pActView->GetWrtShell(); + m_xEdit->set_max(rSh.GetPageCnt()); + m_xEdit->set_width_chars(3); + } + } +} + +void SwNavigationPI::StateChanged(StateChangedType nStateChange) +{ + PanelLayout::StateChanged(nStateChange); + if (nStateChange == StateChangedType::InitShow) + { + // 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. + m_xContent3ToolBox->set_item_sensitive("listbox", SfxChildWindowContext::GetFloatingWindow(GetParent()) != nullptr); + // show content if docked + if (SfxChildWindowContext::GetFloatingWindow(GetParent()) == nullptr && IsZoomedIn()) + ZoomOut(); + } + else if (nStateChange == StateChangedType::ControlFocus) + { + if (m_xContentTree) + { + // 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; + } + } + else + { + if (const SfxEventHint* pHint = dynamic_cast(&rHint)) + { + SfxEventHintId eEventId = pHint->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 OString&, rMenuId, void ) +{ + if (!rMenuId.isEmpty()) + m_xContentTree->SetOutlineLevel(rMenuId.toUInt32()); +} + +void SwNavigationPI::UpdateListBox() +{ + if (isDisposed()) + 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( pItem ); + if( pFrameItem ) + { + SfxViewFrame* pFrame = pFrameItem->GetFrame(); + if(pFrame) + { + m_xContentTree->clear(); + m_pContentView = dynamic_cast( pFrame->GetViewShell() ); + OSL_ENSURE(m_pContentView, "no SwView"); + if(m_pContentView) + m_pContentWrtShell = m_pContentView->GetWrtShellPtr(); + else + m_pContentWrtShell = nullptr; + m_pxObjectShell.reset( new SfxObjectShellLock(pFrame->GetObjectShell()) ); + FillBox(); + } + } +} + +OUString SwNavigationPI::CreateDropFileName( 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_pxObjectShell) + { + m_xContentTree->SetHiddenShell( nullptr ); + (*m_pxObjectShell)->DoClose(); + m_pxObjectShell.reset(); + } + SfxStringItem aFileItem(SID_FILE_NAME, sFileName ); + SfxStringItem aOptionsItem( SID_OPTIONS, "HRC" ); + SfxLinkItem aLink( SID_DONELINK, + LINK( this, SwNavigationPI, DoneLink ) ); + GetActiveView()->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_xContent3ToolBox->set_item_icon_name("dragmode", sImageId); +} + +void SwNavigationPI::ToggleTree() +{ + bool bGlobalDoc = IsGlobalDoc(); + if (!IsGlobalMode() && bGlobalDoc) + { + SetUpdateMode(false); + 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_xDocListBox->hide(); + SetGlobalMode(true); + SetUpdateMode(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_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 (IsDisposed()) + 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(); +} + +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(this)->m_pCreateView = pView; + const_cast(this)->StartListening(*m_pCreateView); + break; + } + pView = SwModule::GetNextView(pView); + } + } + return m_pCreateView; +} + +SwNavigationChild::SwNavigationChild( vcl::Window* pParent, + sal_uInt16 nId, + SfxBindings* _pBindings ) + : SfxChildWindowContext( nId ) +{ + Reference< XFrame > xFrame = _pBindings->GetActiveFrame(); + VclPtr< SwNavigationPI > pNavi = VclPtr< SwNavigationPI >::Create( pParent, xFrame, _pBindings ); + _pBindings->Invalidate(SID_NAVIGATOR); + + SwNavigationConfig* pNaviConfig = SW_MOD()->GetNavigationConfig(); + + const ContentTypeId nRootType = pNaviConfig->GetRootType(); + if( nRootType != ContentTypeId::UNKNOWN ) + { + pNavi->m_xContentTree->SetRootType(nRootType); + pNavi->m_xContent2ToolBox->set_item_active("root", true); + if (nRootType == ContentTypeId::OUTLINE) + { + pNavi->m_xContentTree->set_selection_mode(SelectionMode::Multiple); + } + } + pNavi->m_xContentTree->SetOutlineLevel( static_cast< sal_uInt8 >( pNaviConfig->GetOutlineLevel() ) ); + pNavi->SetRegionDropMode( pNaviConfig->GetRegionMode() ); + + if (SfxNavigator* pNav = dynamic_cast(pParent)) + { + pNav->SetMinOutputSizePixel(pNavi->GetOptimalSize()); + if (pNaviConfig->IsSmall()) + pNavi->ZoomIn(); + } + + SetWindow(pNavi); +} + +/* 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 000000000..4b4b6acb7 --- /dev/null +++ b/sw/source/uibase/utlui/numfmtlb.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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() + : nCurrFormatType(SvNumFormatType::ALL) + , mbCurrFormatTypeNeedsInit(true) + , nStdEntry(0) + , bOneArea(false) + , nDefFormat(0) + , bShowLanguageControl(false) + , bUseAutomaticLanguage(true) +{ +} + +NumFormatListBox::NumFormatListBox(std::unique_ptr xControl) + : mxControl(std::move(xControl)) +{ + Init(); +} + +SwNumFormatTreeView::SwNumFormatTreeView(std::unique_ptr xControl) + : mxControl(std::move(xControl)) +{ + Init(); +} + +void SwNumFormatBase::Init() +{ + SwView *pView = GetActiveView(); + + if (pView) + eCurLanguage = pView->GetWrtShell().GetCurLang(); + else + eCurLanguage = SvtSysLocale().GetLanguageTag().getLanguageType(); + + SetFormatType(SvNumFormatType::NUMBER); + SetDefFormat(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 && + (nCurrFormatType & nFormatType)) // there are mixed formats, like for example DateTime + return; + + SwView *pView = GetActiveView(); + OSL_ENSURE(pView, "no view found"); + 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; + Color* pCol; + double fVal = SwNumFormatBase::GetDefValue(nFormatType); + OUString sValue; + + const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex( + NF_NUMBER_SYSTEM, eCurLanguage ); + const sal_uInt32 nSysShortDateFormat = pFormatter->GetFormatIndex( + NF_DATE_SYSTEM_SHORT, eCurLanguage ); + const sal_uInt32 nSysLongDateFormat = pFormatter->GetFormatIndex( + NF_DATE_SYSTEM_LONG, eCurLanguage ); + + for( long nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex ) + { + const sal_uInt32 nFormat = pFormatter->GetFormatIndex( + static_cast(nIndex), eCurLanguage ); + pFormat = pFormatter->GetEntry( nFormat ); + + if( nFormat == pFormatter->GetFormatIndex( NF_NUMBER_STANDARD, + eCurLanguage ) + || const_cast(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, eCurLanguage ) ) + nStdEntry = i; + ++i; + } + } + + append_text(SwResId(STR_DEFINE_NUMBERFORMAT)); + + set_active(nStdEntry); + + nCurrFormatType = nFormatType; + mbCurrFormatTypeNeedsInit = false; + +} + +void SwNumFormatBase::SetDefFormat(const sal_uInt32 nDefaultFormat) +{ + if (nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + nDefFormat = nDefaultFormat; + return; + } + + SwView *pView = GetActiveView(); + OSL_ENSURE(pView, "no view found"); + if(!pView) + return; + SwWrtShell &rSh = pView->GetWrtShell(); + SvNumberFormatter* pFormatter = rSh.GetNumberFormatter(); + + SvNumFormatType nType = pFormatter->GetType(nDefaultFormat); + + SetFormatType(nType); + + sal_uInt32 nFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nDefaultFormat, eCurLanguage); + + for (sal_Int32 i = 0, nCount = get_count(); i < nCount; ++i) + { + if (nFormat == get_id(i).toUInt32()) + { + set_active(i); + nStdEntry = i; + nDefFormat = GetFormat(); + return; + } + } + + // No entry found: + OUString sValue; + 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, eCurLanguage) ) + { + sValue += SwResId(RID_STR_SYSTEM); + } + + insert_text(nPos, sValue); // Insert as first numeric entry + set_id(nPos, OUString::number(nDefaultFormat)); + set_active(nPos); + 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(); + + SfxItemSet aCoreSet( + rSh.GetAttrPool(), + svl::Items< + 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>{}); + + double fValue = SwNumFormatBase::GetDefValue(nCurrFormatType); + + sal_uInt32 nFormat = pFormatter->GetStandardFormat( nCurrFormatType, eCurLanguage); + aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, nFormat )); + + aCoreSet.Put( SvxNumberInfoItem( pFormatter, fValue, + SID_ATTR_NUMBERFORMAT_INFO ) ); + + if( (SvNumFormatType::DATE | SvNumFormatType::TIME) & nCurrFormatType ) + aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, bOneArea)); + + aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_NOLANGUAGE, !bShowLanguageControl)); + aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ADD_AUTO, bUseAutomaticLanguage)); + + // force deselect to break mouse lock on selected entry + set_active(-1); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateNumFormatDialog(&get_widget(), aCoreSet)); + + if (RET_OK == pDlg->Execute()) + { + const SfxPoolItem* pItem = pView->GetDocShell()-> + GetItem( SID_ATTR_NUMBERFORMAT_INFO ); + + if( pItem ) + { + for ( sal_uInt32 key : static_cast(pItem)->GetDelFormats() ) + pFormatter->DeleteEntry( key ); + } + + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + if( SfxItemState::SET == pOutSet->GetItemState( + SID_ATTR_NUMBERFORMAT_VALUE, false, &pItem )) + { + sal_uInt32 nNumberFormat = static_cast(pItem)->GetValue(); + // oj #105473# change order of calls + const SvNumberformat* pFormat = pFormatter->GetEntry(nNumberFormat); + if( pFormat ) + eCurLanguage = pFormat->GetLanguage(); + // SetDefFormat uses eCurLanguage to look for if this format already in the list + SetDefFormat(nNumberFormat); + } + if( bShowLanguageControl && SfxItemState::SET == pOutSet->GetItemState( + SID_ATTR_NUMBERFORMAT_ADD_AUTO, false, &pItem )) + { + bUseAutomaticLanguage = static_cast(pItem)->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; + 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 000000000..2cefdc4ff --- /dev/null +++ b/sw/source/uibase/utlui/prcntfld.cxx @@ -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 . + */ + +#include +#include + +SwPercentField::SwPercentField(std::unique_ptr pControl) + : m_pField(std::move(pControl)) + , nOldMax(0) + , nOldMin(0) + , nLastPercent(-1) + , nLastValue(-1) + , nOldDigits(m_pField->get_digits()) + , eOldUnit(FieldUnit::NONE) + , bLockAutoCalculation(false) +{ + int nMin, nMax; + m_pField->get_range(nMin, nMax, FieldUnit::TWIP); + nRefValue = DenormalizePercent(nMax); + m_pField->get_increments(nOldSpinSize, nOldPageSize, FieldUnit::NONE); +} + +void SwPercentField::SetRefValue(int nValue) +{ + int nRealValue = GetRealValue(eOldUnit); + + nRefValue = nValue; + + if (!bLockAutoCalculation && (m_pField->get_unit() == FieldUnit::PERCENT)) + set_value(nRealValue, eOldUnit); +} + +void SwPercentField::ShowPercent(bool bPercent) +{ + if ((bPercent && m_pField->get_unit() == FieldUnit::PERCENT) || + (!bPercent && m_pField->get_unit() != FieldUnit::PERCENT)) + return; + + int nOldValue; + + if (bPercent) + { + nOldValue = get_value(); + + eOldUnit = m_pField->get_unit(); + nOldDigits = m_pField->get_digits(); + m_pField->get_range(nOldMin, nOldMax, FieldUnit::NONE); + m_pField->get_increments(nOldSpinSize, nOldPageSize, FieldUnit::NONE); + m_pField->set_unit(FieldUnit::PERCENT); + m_pField->set_digits(0); + + int nCurrentWidth = vcl::ConvertValue(nOldMin, 0, nOldDigits, eOldUnit, FieldUnit::TWIP); + // round to 0.5 percent + int nPercent = nRefValue ? (((nCurrentWidth * 10) / 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 != nLastValue) + { + nCurrentWidth = vcl::ConvertValue(nOldValue, 0, nOldDigits, eOldUnit, FieldUnit::TWIP); + nPercent = nRefValue ? (((nCurrentWidth * 10) / nRefValue + 5) / 10) : 0; + m_pField->set_value(nPercent, FieldUnit::NONE); + nLastPercent = nPercent; + nLastValue = nOldValue; + } + else + m_pField->set_value(nLastPercent, FieldUnit::NONE); + } + else + { + int nOldPercent = get_value(FieldUnit::PERCENT); + + nOldValue = Convert(get_value(), m_pField->get_unit(), eOldUnit); + + m_pField->set_unit(eOldUnit); + m_pField->set_digits(nOldDigits); + m_pField->set_range(nOldMin, nOldMax, FieldUnit::NONE); + m_pField->set_increments(nOldSpinSize, nOldPageSize, FieldUnit::NONE); + + if (nOldPercent != nLastPercent) + { + set_value(nOldValue, eOldUnit); + nLastPercent = nOldPercent; + nLastValue = nOldValue; + } + else + set_value(nLastValue, eOldUnit); + } +} + +void SwPercentField::set_value(int 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 + int nPercent, nCurrentWidth; + if(eInUnit == FieldUnit::TWIP) + { + nCurrentWidth = vcl::ConvertValue(nNewValue, 0, nOldDigits, FieldUnit::TWIP, FieldUnit::TWIP); + } + else + { + int nValue = Convert(nNewValue, eInUnit, eOldUnit); + nCurrentWidth = vcl::ConvertValue(nValue, 0, nOldDigits, eOldUnit, FieldUnit::TWIP); + } + nPercent = nRefValue ? (((nCurrentWidth * 10) / nRefValue + 5) / 10) : 0; + m_pField->set_value(nPercent, FieldUnit::NONE); + } +} + +int SwPercentField::get_value(FieldUnit eOutUnit) +{ + return Convert(m_pField->get_value(FieldUnit::NONE), m_pField->get_unit(), eOutUnit); +} + +void SwPercentField::set_min(int nNewMin, FieldUnit eInUnit) +{ + if (m_pField->get_unit() != FieldUnit::PERCENT) + m_pField->set_min(nNewMin, eInUnit); + else + { + if (eInUnit == FieldUnit::NONE) + eInUnit = eOldUnit; + nOldMin = Convert(nNewMin, eInUnit, eOldUnit); + + int nPercent = Convert(nNewMin, eInUnit, FieldUnit::PERCENT); + m_pField->set_min(std::max(1, nPercent), FieldUnit::NONE); + } +} + +void SwPercentField::set_max(int nNewMax, FieldUnit eInUnit) +{ + if (m_pField->get_unit() != FieldUnit::PERCENT) + m_pField->set_max(nNewMax, eInUnit); +} + +int SwPercentField::NormalizePercent(int nValue) +{ + if (m_pField->get_unit() != FieldUnit::PERCENT) + nValue = m_pField->normalize(nValue); + else + nValue = nValue * ImpPower10(nOldDigits); + return nValue; +} + +int SwPercentField::DenormalizePercent(int nValue) +{ + if (m_pField->get_unit() != FieldUnit::PERCENT) + nValue = m_pField->denormalize(nValue); + else + { + int nFactor = ImpPower10(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; +} + +int 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); +} + +int SwPercentField::Convert(int 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 + int nTwipValue = (nRefValue * nValue + 50) / 100; + + if (eOutUnit == FieldUnit::TWIP) // Only convert if necessary + return NormalizePercent(nTwipValue); + else + return vcl::ConvertValue(NormalizePercent(nTwipValue), 0, nOldDigits, FieldUnit::TWIP, eOutUnit); + } + + if (eOutUnit == FieldUnit::PERCENT) + { + // Convert to percent + int nCurrentWidth; + nValue = DenormalizePercent(nValue); + + if (eInUnit == FieldUnit::TWIP) // Only convert if necessary + nCurrentWidth = nValue; + else + nCurrentWidth = vcl::ConvertValue(nValue, 0, nOldDigits, eInUnit, FieldUnit::TWIP); + // Round to 0.5 percent + return nRefValue ? (((nCurrentWidth * 1000) / nRefValue + 5) / 10) : 0; + } + + return vcl::ConvertValue(nValue, 0, 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 000000000..dbdf78b49 --- /dev/null +++ b/sw/source/uibase/utlui/shdwcrsr.cxx @@ -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 . + */ + +#include +#include +#include + +using namespace ::com::sun::star; + +SwShadowCursor::~SwShadowCursor() +{ + if( USHRT_MAX != nOldMode ) + DrawCursor( aOldPt, nOldHeight, nOldMode ); +} + +void SwShadowCursor::SetPos( const Point& rPt, long nHeight, sal_uInt16 nMode ) +{ + Point aPt( pWin->LogicToPixel( rPt )); + nHeight = pWin->LogicToPixel( Size( 0, nHeight )).Height(); + if( aOldPt != aPt || nOldHeight != nHeight || nOldMode != nMode ) + { + if( USHRT_MAX != nOldMode ) + DrawCursor( aOldPt, nOldHeight, nOldMode ); + + DrawCursor( aPt, nHeight, nMode ); + nOldMode = nMode; + nOldHeight = nHeight; + aOldPt = aPt; + } +} + +void SwShadowCursor::DrawTri( const Point& rPt, long nHeight, bool bLeft ) +{ + long nLineDiff = nHeight / 2; + long nLineDiffHalf = nLineDiff / 2; + + // Dot above + Point aPt1( (bLeft ? rPt.X() - 3 : rPt.X() + 3), + rPt.Y() + nLineDiffHalf ); + // Dot below + Point aPt2( aPt1.X(), aPt1.Y() + nHeight - nLineDiff - 1 ); + long nDiff = bLeft ? -1 : 1; + while( aPt1.Y() <= aPt2.Y() ) + { + pWin->DrawLine( aPt1, aPt2 ); + aPt1.AdjustY( 1 ); + aPt2.AdjustY( -1 ); + aPt2.setX( aPt1.AdjustX(nDiff ) ); + } +} + +void SwShadowCursor::DrawCursor( const Point& rPt, long nHeight, sal_uInt16 nMode ) +{ + nHeight = (((nHeight / 4)+1) * 4) + 1; + + pWin->Push(); + + pWin->SetMapMode(MapMode(MapUnit::MapPixel)); + pWin->SetRasterOp( RasterOp::Xor ); + + pWin->SetLineColor( Color( sal_uInt32(aCol) ^ sal_uInt32(COL_WHITE) ) ); + + // 1. The Line: + pWin->DrawLine( Point( rPt.X(), rPt.Y() + 1), + Point( rPt.X(), rPt.Y() - 2 + nHeight )); + + // 2. The Triangle + if( text::HoriOrientation::LEFT == nMode || text::HoriOrientation::CENTER == nMode ) // Arrow to the right + DrawTri( rPt, nHeight, false ); + if( text::HoriOrientation::RIGHT == nMode || text::HoriOrientation::CENTER == nMode ) // Arrow to the left + DrawTri( rPt, nHeight, true ); + + pWin->Pop(); +} + +void SwShadowCursor::Paint() +{ + if( USHRT_MAX != nOldMode ) + DrawCursor( aOldPt, nOldHeight, nOldMode ); +} + +tools::Rectangle SwShadowCursor::GetRect() const +{ + long nH = nOldHeight; + Point aPt( aOldPt ); + + nH = (((nH / 4)+1) * 4) + 1; + long nWidth = nH / 4 + 3 + 1; + + Size aSz( nWidth, nH ); + + if( text::HoriOrientation::RIGHT == nOldMode ) + aPt.AdjustX( -(aSz.Width()) ); + else if( text::HoriOrientation::CENTER == nOldMode ) + { + aPt.AdjustX( -(aSz.Width()) ); + aSz.setWidth( aSz.Width() * 2 ); + } + + return pWin->PixelToLogic( tools::Rectangle( aPt, aSz ) ); +} + +/* 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 000000000..2220c776e --- /dev/null +++ b/sw/source/uibase/utlui/tmplctrl.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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +SFX_IMPL_STATUSBAR_CONTROL( SwTemplateControl, SfxStringItem ); + +namespace { + +class SwTemplatePopup_Impl : public PopupMenu +{ +public: + SwTemplatePopup_Impl(); + + sal_uInt16 GetCurId() const { return nCurId; } + +private: + sal_uInt16 nCurId; + + virtual void Select() override; +}; + +} + +SwTemplatePopup_Impl::SwTemplatePopup_Impl() : + PopupMenu(), + nCurId(USHRT_MAX) +{ +} + +void SwTemplatePopup_Impl::Select() +{ + nCurId = GetCurItemId(); +} + +SwTemplateControl::SwTemplateControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SfxStatusBarControl( _nSlotId, _nId, rStb ) +{ + GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_TMPLCTRL_HINT)); +} + +SwTemplateControl::~SwTemplateControl() +{ +} + +void SwTemplateControl::StateChanged( + sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + const SfxStringItem* pItem = nullptr; + if (SfxItemState::DEFAULT == eState && (pItem = dynamic_cast(pState))) + { + sTemplate = pItem->GetValue(); + GetStatusBar().SetItemText(GetId(), sTemplate); + } + else + GetStatusBar().SetItemText(GetId(), OUString()); +} + +void SwTemplateControl::Paint( const UserDrawEvent& ) +{ +} + +void SwTemplateControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == CommandEventId::ContextMenu && + !GetStatusBar().GetItemText( GetId() ).isEmpty() ) + { + ScopedVclPtrInstance aPop; + { + 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) + { + sal_uInt16 nCount = 0; + SfxStyleSheetBase* pStyle = xIter->First(); + while( pStyle ) + { + aPop->InsertItem( ++nCount, pStyle->GetName() ); + pStyle = xIter->Next(); + } + + aPop->Execute( &GetStatusBar(), rCEvt.GetMousePosPixel()); + const sal_uInt16 nCurrId = aPop->GetCurId(); + if( nCurrId != USHRT_MAX) + { + // 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 000000000..e6673587c --- /dev/null +++ b/sw/source/uibase/utlui/uiitems.cxx @@ -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 . + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +SwPageFootnoteInfoItem::SwPageFootnoteInfoItem( SwPageFootnoteInfo const & rInfo) : + SfxPoolItem( FN_PARAM_FTN_INFO ), + 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) + && aFootnoteInfo == static_cast(rAttr).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(convertTwipToMm100(aFootnoteInfo.GetHeight()));break; + case MID_LINE_WEIGHT : rVal <<= static_cast(convertTwipToMm100(aFootnoteInfo.GetLineWidth()));break; + case MID_LINE_COLOR : rVal <<= aFootnoteInfo.GetLineColor();break; + case MID_LINE_RELWIDTH : + { + Fraction aTmp( 100, 1 ); + aTmp *= aFootnoteInfo.GetWidth(); + rVal <<= static_cast(static_cast(aTmp)); + } + break; + case MID_LINE_ADJUST : rVal <<= static_cast(aFootnoteInfo.GetAdj());break;//text::HorizontalAdjust + case MID_LINE_TEXT_DIST : rVal <<= static_cast(convertTwipToMm100(aFootnoteInfo.GetTopDist()));break; + case MID_LINE_FOOTNOTE_DIST: rVal <<= static_cast(convertTwipToMm100(aFootnoteInfo.GetBottomDist()));break; + case MID_FTN_LINE_STYLE : + { + switch ( 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; + 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 = convertMm100ToTwip(nSet32); + switch(nMemberId & ~CONVERT_TWIPS) + { + case MID_FTN_HEIGHT: aFootnoteInfo.SetHeight(nSet32); break; + case MID_LINE_TEXT_DIST: aFootnoteInfo.SetTopDist(nSet32);break; + case MID_LINE_FOOTNOTE_DIST: aFootnoteInfo.SetBottomDist(nSet32);break; + } + } + break; + case MID_LINE_WEIGHT : + { + sal_Int16 nSet = 0; + rVal >>= nSet; + if(nSet >= 0) + aFootnoteInfo.SetLineWidth(convertMm100ToTwip(nSet)); + else + bRet = false; + } + break; + case MID_LINE_RELWIDTH : + { + sal_Int8 nSet = 0; + rVal >>= nSet; + if(nSet < 0) + bRet = false; + else + aFootnoteInfo.SetWidth(Fraction(nSet, 100)); + } + break; + case MID_LINE_ADJUST : + { + sal_Int16 nSet = 0; + rVal >>= nSet; + if(nSet >= 0 && nSet < 3) //text::HorizontalAdjust + aFootnoteInfo.SetAdj(static_cast(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; + } + aFootnoteInfo.SetLineStyle( eStyle ); + } + break; + default: + bRet = false; + } + return bRet; +} + +SwPtrItem::SwPtrItem( const sal_uInt16 nId, void* pPtr ) : + SfxPoolItem( nId ), + pMisc(pPtr) +{ +} + +// Cloning + +SwPtrItem* SwPtrItem::Clone( SfxItemPool * /*pPool*/ ) const +{ + return new SwPtrItem( *this ); +} + +bool SwPtrItem::operator==( const SfxPoolItem& rAttr ) const +{ + return SfxPoolItem::operator==(rAttr) + && pMisc == static_cast(rAttr).pMisc; +} + +// SwUINumRuleItem for the NumTabPages of the FormatNumRule/Styleists + +SwUINumRuleItem::SwUINumRuleItem( const SwNumRule& rRul ) + : SfxPoolItem( FN_PARAM_ACT_NUMBER ), pRule( new SwNumRule( rRul ) ) +{ +} + +SwUINumRuleItem::SwUINumRuleItem( const SwUINumRuleItem& rItem ) + : SfxPoolItem( rItem ), + pRule( new SwNumRule( *rItem.pRule )) +{ +} + +SwUINumRuleItem::~SwUINumRuleItem() +{ +} + +SwUINumRuleItem* SwUINumRuleItem::Clone( SfxItemPool * /*pPool*/ ) const +{ + return new SwUINumRuleItem( *this ); +} + +bool SwUINumRuleItem::operator==( const SfxPoolItem& rAttr ) const +{ + return SfxPoolItem::operator==(rAttr) + && *pRule == *static_cast(rAttr).pRule; +} + +bool SwUINumRuleItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const +{ + uno::Reference< container::XIndexReplace >xRules = new SwXNumberingRules(*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 = comphelper::getUnoTunnelImplementation(xRulesRef); + if(pSwXRules) + { + *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(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 000000000..fb41aaa6f --- /dev/null +++ b/sw/source/uibase/utlui/uitool.cxx @@ -0,0 +1,848 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +// 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 aBoxInfo(std::make_shared(SID_ATTR_BORDER_INNER)); + const SfxPoolItem *pBoxInfo; + + if ( SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, true, &pBoxInfo)) + { + aBoxInfo.reset(static_cast(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) +{ + // Background / highlight + { + // Always use the visible background + const SfxPoolItem *pTmpBrush; + if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_HIGHLIGHT, true, &pTmpBrush ) ) + { + SvxBrushItem aTmpBrush( *static_cast(pTmpBrush) ); + if( aTmpBrush.GetColor() != COL_TRANSPARENT ) + { + aTmpBrush.SetWhich( RES_CHRATR_BACKGROUND ); + rSet.Put( aTmpBrush ); + } + } + } + + // 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 + const sal_uInt16* pRanges = rSet.GetRanges(); + const sal_uInt16* pEnd = pRanges; + while (*pEnd) + ++pEnd; + const uno::Sequence aOrigRanges(pRanges, pEnd - pRanges + 1); + aGrabBag.GetGrabBag()["OrigItemSetRanges"] <<= aOrigRanges; + rSet.MergeRange(RES_PARATR_GRABBAG, RES_PARATR_GRABBAG); + rSet.Put(aGrabBag); +} + +void ConvertAttrGenToChar(SfxItemSet& rSet, const SfxItemSet& rOrigSet) +{ + // Background / highlighting + const SfxPoolItem *pTmpItem; + if( SfxItemState::SET == rSet.GetItemState( RES_CHRATR_BACKGROUND, false, &pTmpItem ) ) + { + // 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 (SfxItemState::SET == rOrigSet.GetItemState(RES_CHRATR_GRABBAG, false, &pTmpItem)) + { + SfxGrabBagItem aGrabBag(*static_cast(pTmpItem)); + std::map& rMap = aGrabBag.GetGrabBag(); + auto aIterator = rMap.find("CharShadingMarker"); + if( aIterator != rMap.end() ) + { + aIterator->second <<= false; + } + rSet.Put( aGrabBag ); + } + } + rSet.ClearItem( RES_BACKGROUND ); + + if (SfxItemState::SET == rOrigSet.GetItemState(RES_PARATR_GRABBAG, false, &pTmpItem)) + { + SfxGrabBagItem aGrabBag(*static_cast(pTmpItem)); + std::map& rMap = aGrabBag.GetGrabBag(); + auto aIterator = rMap.find("OrigItemSetRanges"); + if (aIterator != rMap.end()) + { + if (uno::Sequence aOrigRanges; (aIterator->second >>= aOrigRanges) + && aOrigRanges.getLength() % 2 == 1 + && *(std::cend(aOrigRanges) - 1) == 0) + rSet.SetRanges(aOrigRanges.getConstArray()); + } + } + assert(SfxItemState::SET != rSet.GetItemState(RES_PARATR_GRABBAG, false)); +} + +void ApplyCharBackground(const Color& rBackgroundColor, SwWrtShell& rShell) +{ + rShell.StartUndo(SwUndoId::INSATTR); + + SfxItemSet aCoreSet(rShell.GetView().GetPool(), svl::Items< + RES_CHRATR_GRABBAG, RES_CHRATR_GRABBAG>{}); + + rShell.GetCurAttr(aCoreSet); + + // Set char background + rShell.SetAttrItem(SvxBrushItem(rBackgroundColor, 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 + const SfxPoolItem *pTmpItem; + if (SfxItemState::SET == aCoreSet.GetItemState(RES_CHRATR_GRABBAG, false, &pTmpItem)) + { + SfxGrabBagItem aGrabBag(*static_cast(pTmpItem)); + std::map& 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; + + // 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 + const SfxPoolItem* pItem; + if( SfxItemState::SET == rSet.GetItemState( SID_ATTR_PAGE_HEADERSET, + false, &pItem ) ) + { + const SfxItemSet& rHeaderSet = static_cast(pItem)->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( + 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( SfxItemState::SET == rSet.GetItemState( SID_ATTR_PAGE_FOOTERSET, + false, &pItem ) ) + { + const SfxItemSet& rFooterSet = static_cast(pItem)->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( + rFooterSet.Get(SID_ATTR_PAGE_SHARED_FIRST)).GetValue()); + } + } + else + { + // Disable footer + if(rMaster.GetFooter().IsActive()) + { + rMaster.SetFormatAttr(SwFormatFooter(false)); + rPageDesc.ChgFooterShare(false); + } + } + } + + // Footnotes + + if( SfxItemState::SET == rSet.GetItemState( FN_PARAM_FTN_INFO, + false, &pItem ) ) + rPageDesc.SetFootnoteInfo( static_cast(pItem)->GetPageFootnoteInfo() ); + + // Columns + + // Register compliant + + if(SfxItemState::SET == rSet.GetItemState( + SID_SWREGISTER_MODE, false, &pItem)) + { + bool bSet = static_cast(pItem)->GetValue(); + if(!bSet) + rPageDesc.SetRegisterFormatColl(nullptr); + else if(SfxItemState::SET == rSet.GetItemState( + SID_SWREGISTER_COLLECTION, false, &pItem)) + { + const OUString& rColl = static_cast(pItem)->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 ); + } + } +} + +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 aBoxInfo(std::make_shared(SID_ATTR_BORDER_INNER)); + const SfxPoolItem *pBoxInfo; + + if ( SfxItemState::SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, true, &pBoxInfo) ) + { + aBoxInfo.reset(static_cast(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 + SfxItemSet aHeaderSet(*rSet.GetPool(), + svl::Items{}); + + // 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 + SfxItemSet aFooterSet(*rSet.GetPool(), + svl::Items{}); + + // 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(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())); + +} + +// 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(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( SfxItemState::SET == rSet.GetItemState( SID_ATTR_PARA_MODEL, false, &pItem )) + { + const OUString& rDescName = static_cast(pItem)->GetValue(); + if( !rDescName.isEmpty() ) // No name -> disable PageDesc! + { + // Delete only, if PageDesc will be enabled! + rSet.ClearItem( RES_BREAK ); + SwPageDesc* pDesc = const_cast(rShell).FindPageDescByName( + rDescName, true ); + if( pDesc ) + aPgDesc.RegisterToPageDesc( *pDesc ); + } + rSet.ClearItem( SID_ATTR_PARA_MODEL ); + bChanged = true; + } + else + { + SfxItemSet aCoreSet(rShell.GetView().GetPool(), svl::Items{} ); + rShell.GetCurAttr( aCoreSet ); + if(SfxItemState::SET == aCoreSet.GetItemState( RES_PAGEDESC, true, &pItem ) ) + { + if( static_cast(pItem)->GetPageDesc() ) + { + aPgDesc.RegisterToPageDesc( *const_cast(static_cast(pItem))->GetPageDesc() ); + } + } + } + + if(bChanged) + rSet.Put( aPgDesc ); +} + +// Inquire if in the set is a Sfx-PageDesc combination present and return it. +void SwToSfxPageDescAttr( SfxItemSet& rCoreSet ) +{ + const SfxPoolItem* pItem = nullptr; + OUString aName; + ::std::optional oNumOffset; + bool bPut = true; + switch( rCoreSet.GetItemState( RES_PAGEDESC, true, &pItem ) ) + { + case SfxItemState::SET: + { + if( static_cast(pItem)->GetPageDesc() ) + { + aName = static_cast(pItem)->GetPageDesc()->GetName(); + oNumOffset = static_cast(pItem)->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( PopupMenu const & rMenu, SfxViewFrame const & rViewFrame, sal_uInt16 nId ) +{ + bool bRet = false; + const sal_uInt16 nItemCount = rMenu.GetItemCount(); + OUString sCommand; + for( sal_uInt16 nItem = 0; nItem < nItemCount; ++nItem) + { + PopupMenu* pPopup = rMenu.GetPopupMenu( rMenu.GetItemId( nItem ) ); + if(pPopup) + { + sCommand = pPopup->GetItemCommand(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 000000000..fbad314f1 --- /dev/null +++ b/sw/source/uibase/utlui/unotools.cxx @@ -0,0 +1,510 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; + +const char cFactory[] = "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::makeAny(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::makeAny(true)); + } +} + +static const sal_Int16 nZoomValues[] = +{ + 20, + 40, + 50, + 75, + 100 +}; + +SwOneExampleFrame::SwOneExampleFrame(sal_uInt32 nFlags, + const Link* 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::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); + + auto pCursor = comphelper::getUnoTunnelImplementation(m_xCursor); + if (pCursor) + { + uno::Reference xSettings(m_xController, uno::UNO_QUERY); + uno::Reference 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(PushFlags::ALL); + m_xVirDev->SetMapMode(MapMode(MapUnit::MapTwip)); + SwDoc *pDoc = pCursor->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); + 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 xDesktop = frame::Desktop::create(::comphelper::getProcessComponentContext()); + uno::Sequence 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 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(); + m_xCursor = xText->createTextCursor(); + + //From here, a cursor is defined, which goes through the template, + //and overwrites the template words where it is necessary. + + auto pCursor = comphelper::getUnoTunnelImplementation(m_xCursor); + + SwDoc *pDoc = pCursor ? pCursor->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), sal_uInt16(1), true)); + + TOXTypes eTypes[] = { TOX_INDEX, TOX_USER, TOX_CONTENT }; + for (auto eType : eTypes) + { + const SwTOXType* pTOXType = pDoc->GetTOXType(eType, 0); + SwTOXMarks aMarks; + SwTOXMark::InsertTOXMarks(aMarks, *pTOXType); + 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::Reference< beans::XPropertySet > xCursorProp(m_xCursor, uno::UNO_QUERY); + uno::Any aPageStyle = xCursorProp->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 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() +{ + uno::Reference< lang::XUnoTunnel> xTunnel( m_xCursor, uno::UNO_QUERY); + if( xTunnel.is() ) + { + OTextCursorHelper* pCursor = reinterpret_cast(xTunnel->getSomething( + OTextCursorHelper::getUnoTunnelId()) ); + if( pCursor ) + { + SwDoc* pDoc = pCursor->GetDoc(); + SwEditShell* pSh = pDoc->GetEditShell(); + pSh->LockPaint(); + pSh->StartAllAction(); + pSh->KillPams(); + pSh->ClearMark(); + pDoc->ClearDoc(); + pSh->ClearUpCursors(); + + if( m_aLoadedIdle.IsActive()) + { + pSh->EndAllAction(); + pSh->UnlockPaint(); + } + m_aLoadedIdle.Start(); + } + else + { + m_xCursor->gotoStart(false); + m_xCursor->gotoEnd(true); + m_xCursor->setString(OUString()); + } + } +} + +bool SwOneExampleFrame::CreatePopup(const Point& rPt) +{ + if (EX_SHOW_ONLINE_LAYOUT != m_nStyleFlags) + return false; + + std::unique_ptr xBuilder(Application::CreateBuilder(nullptr, "modules/swriter/ui/previewmenu.ui")); + std::unique_ptr 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 (size_t i = 0; i < SAL_N_ELEMENTS(nZoomValues); ++i) + { + OUString sTemp = unicode::formatPercent(nZoomValues[i], + Application::GetSettings().GetUILanguageTag()); + OString sIdent = "zoom" + OString::number(nZoomValues[i]); + xPop->set_label(sIdent, sTemp); + if (nZoom == nZoomValues[i]) + xPop->set_active(sIdent, true); + } + + PopupHdl(xPop->popup_at_rect(GetDrawingArea(), tools::Rectangle(rPt, Size(1, 1)))); + + return true; +} + +void SwOneExampleFrame::PopupHdl(const OString& rId) +{ + OString sZoomValue; + if (rId.startsWith("zoom", &sZoomValue)) + { + sal_Int16 nZoom = sZoomValue.toInt32(); + 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 000000000..bdb18bbb3 --- /dev/null +++ b/sw/source/uibase/utlui/viewlayoutctrl.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 + +#include +#include +#include +#include +#include +#include +#include +#include + +SFX_IMPL_STATUSBAR_CONTROL( SwViewLayoutControl, SvxViewLayoutItem ); + +struct SwViewLayoutControl::SwViewLayoutControl_Impl +{ + sal_uInt16 mnState; // 0 = auto, 1= single, 2 = book, 3 = none + 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::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + if ( SfxItemState::DEFAULT != eState || pState->IsVoidItem() ) + GetStatusBar().SetItemText( GetId(), OUString() ); + else + { + OSL_ENSURE( dynamic_cast< const SvxViewLayoutItem *>( pState ) != nullptr, "invalid item type" ); + const sal_uInt16 nColumns = static_cast( pState )->GetValue(); + const bool bBookMode = static_cast( 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(); + + const bool bSingleColumn = 0 == mpImpl->mnState; + const bool bAutomatic = 1 == mpImpl->mnState; + const bool bBookMode = 2 == mpImpl->mnState; + + const long nImageWidthSum = mpImpl->maImageSingleColumn.GetSizePixel().Width() + + mpImpl->maImageAutomatic.GetSizePixel().Width() + + mpImpl->maImageBookMode.GetSizePixel().Width(); + + const long nXOffset = (aRect.GetWidth() - nImageWidthSum) / 2; + const 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() ); + pDev->DrawImage( aRect.TopLeft(), bAutomatic ? mpImpl->maImageAutomatic_Active : mpImpl->maImageAutomatic ); + + // draw bookmode image: + aRect.AdjustLeft(mpImpl->maImageAutomatic.GetSizePixel().Width() ); + pDev->DrawImage( aRect.TopLeft(), bBookMode ? mpImpl->maImageBookMode_Active : mpImpl->maImageBookMode ); +} + +bool SwViewLayoutControl::MouseButtonDown( const MouseEvent & rEvt ) +{ + const tools::Rectangle aRect = getControlRect(); + const Point aPoint = rEvt.GetPosPixel(); + const long nXDiff = aPoint.X() - aRect.Left(); + + sal_uInt16 nColumns = 1; + bool bBookMode = false; + + const long nImageWidthSingle = mpImpl->maImageSingleColumn.GetSizePixel().Width(); + const long nImageWidthAuto = mpImpl->maImageAutomatic.GetSizePixel().Width(); + const long nImageWidthBook = mpImpl->maImageBookMode.GetSizePixel().Width(); + const long nImageWidthSum = nImageWidthSingle + nImageWidthAuto + nImageWidthBook; + + const 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( 1 ); + aArgs[0].Name = "ViewLayout"; + aArgs[0].Value = a; + + execute( aArgs ); + + return true; +} + +bool SwViewLayoutControl::MouseMove( const MouseEvent & rEvt ) +{ + const tools::Rectangle aRect = getControlRect(); + const Point aPoint = rEvt.GetPosPixel(); + const long nXDiff = aPoint.X() - aRect.Left(); + + const long nImageWidthSingle = mpImpl->maImageSingleColumn.GetSizePixel().Width(); + const long nImageWidthAuto = mpImpl->maImageAutomatic.GetSizePixel().Width(); + const long nImageWidthBook = mpImpl->maImageBookMode.GetSizePixel().Width(); + const long nImageWidthSum = nImageWidthSingle + nImageWidthAuto + nImageWidthBook; + + const 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 000000000..93eba3c73 --- /dev/null +++ b/sw/source/uibase/utlui/wordcountctrl.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/. + */ + +#include +#include +#include +#include +#include + +SFX_IMPL_STATUSBAR_CONTROL(SwWordCountStatusBarControl, SfxStringItem); + +SwWordCountStatusBarControl::SwWordCountStatusBarControl( + sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb) : + SfxStatusBarControl(_nSlotId, _nId, rStb) +{ +} + +SwWordCountStatusBarControl::~SwWordCountStatusBarControl() +{ +} + +void SwWordCountStatusBarControl::StateChanged( + sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState ) +{ + if (eState == SfxItemState::DEFAULT) // Can access pState + GetStatusBar().SetItemText( GetId(), static_cast(pState)->GetValue() ); + + GetStatusBar().SetQuickHelpText(GetId(), SwResId(STR_WORDCOUNT_HINT)); +} + +/* 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 000000000..493b2f9b7 --- /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 +#include +#include + +#include + +SFX_IMPL_STATUSBAR_CONTROL( SwZoomControl, SvxZoomItem ); + +SwZoomControl::SwZoomControl( sal_uInt16 _nSlotId, + sal_uInt16 _nId, + StatusBar& rStb ) : + SvxZoomStatusBarControl( _nSlotId, _nId, rStb ) +{ +} + +SwZoomControl::~SwZoomControl() +{ +} + +void SwZoomControl::StateChanged( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) +{ + const SfxStringItem* pItem = nullptr; + if (SfxItemState::DEFAULT == eState && (pItem = dynamic_cast(pState))) + { + sPreviewZoom = pItem->GetValue(); + GetStatusBar().SetItemText(GetId(), sPreviewZoom); + } + else + { + sPreviewZoom.clear(); + SvxZoomStatusBarControl::StateChanged(nSID, eState, pState); + } +} + +void SwZoomControl::Paint( const UserDrawEvent& ) +{ +} + +void SwZoomControl::Command( const CommandEvent& rCEvt ) +{ + if (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 000000000..05242544f --- /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 + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebDocShell +#include + +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 000000000..1d65b62b3 --- /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 +#include +#include + +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebDrawFormShell +#include + +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 000000000..a9bac1962 --- /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 +#include +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebFrameShell +#include +#include + +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 000000000..66fc2235d --- /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 + +#include + +#include +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebGrfShell +#include + +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 000000000..c7789c1e4 --- /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 +#include + +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebListShell +#include + +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 000000000..15bab538b --- /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 +#include + +#include +#include + +#define ShellClass_SwWebOleShell +#include + +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 000000000..88008034c --- /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 + +#include +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebTableShell +#include +#include + +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 000000000..c655bdf2c --- /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 + +#include +#include +#include +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#define ShellClass_SwWebTextShell +#include +#include + +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 000000000..2fa09630e --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TECHNICALLY not possible !! +#include +#include +#include +#include + +#include +#include + + // needed for -fsanitize=function visibility of typeinfo for functions of + // type void(SfxShell*,SfxRequest&) defined in swslots.hxx +#include +#define ShellClass_SwWebView +#define ShellClass_Text +#include + +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* _pFrame, SfxViewShell* _pShell) : + SwView(_pFrame, _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 000000000..0dbc7eb89 --- /dev/null +++ b/sw/source/uibase/wrtsh/delete.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + SfxItemSet aAttrSet(GetAttrPool(), svl::Items{}); + GetCurAttr(aAttrSet); + + SvxLRSpaceItem aItem = aAttrSet.Get(RES_LR_SPACE); + short aOldFirstLineOfst = aItem.GetTextFirstLineOffset(); + + if (aOldFirstLineOfst > 0) + { + aItem.SetTextFirstLineOffset(0); + bResult = true; + } + else if (aOldFirstLineOfst < 0) + { + aItem.SetTextFirstLineOffset(0); + aItem.SetLeft(aItem.GetLeft() + aOldFirstLineOfst); + + bResult = true; + } + else if (aItem.GetLeft() != 0) + { + aItem.SetLeft(0); + bResult = true; + } + + if (bResult) + { + aAttrSet.Put(aItem); + 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(); + Pop(SwCursorShell::PopMode::DeleteCurrent); + if( bRet ) + UpdateAttr(); +} + +void SwWrtShell::DelToStartOfLine() +{ + OpenMark(); + SwCursorShell::LeftMargin(); + bool bRet = Delete(); + CloseMark( bRet ); +} + +void SwWrtShell::DelToEndOfLine() +{ + OpenMark(); + SwCursorShell::RightMargin(); + bool bRet = Delete(); + 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(); + 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 ? + GetSwCursor()->GetNode().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,CRSR_SKIP_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 ? + GetSwCursor()->GetNode().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,CRSR_SKIP_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); + --aPrevChar.nContent; + 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, CRSR_SKIP_CHARS); + if (SvtScriptType::ASIAN == GetScriptType()) + { + sal_uInt32 nCode = GetChar(false); + if ( rtl::isSurrogate( nCode ) ) + { + OUString sStr = GetSelText(); + sal_Int32 nIndex = 0; + nCode = sStr.iterateCodePoints( &nIndex ); + } + + if ( unicode::isIVSSelector( nCode ) ) + { + SwCursorShell::Push(); + SwCursorShell::Left(1, CRSR_SKIP_CHARS); + OUString sStr = GetSelText(); + sal_Int32 nIndex = 0; + nCode = sStr.iterateCodePoints( &nIndex ); + if ( unicode::isCJKIVSCharacter( nCode ) ) + SwCursorShell::Pop( SwCursorShell::PopMode::DeleteStack ); + else + SwCursorShell::Pop( SwCursorShell::PopMode::DeleteCurrent ); // For the weak script. + } + } + } + bool bRet = Delete(); + if( !bRet && bSwap ) + SwCursorShell::SwapPam(); + CloseMark( bRet ); + if (!bRet) + { // false indicates HasReadonlySel failed + std::unique_ptr xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xInfo->run(); + } + return bRet; +} + +bool SwWrtShell::DelRight() +{ + // 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 ) + { + 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(); + 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 ? + GetSwCursor()->GetNode().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, CRSR_SKIP_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 ? + GetSwCursor()->GetNode().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, CRSR_SKIP_CELLS); + bRet = Delete(); + CloseMark( bRet ); + if (!bRet) + { // false indicates HasReadonlySel failed + std::unique_ptr xBuilder(Application::CreateBuilder(GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); + std::unique_ptr xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); + xInfo->run(); + } + break; + + case SelectionType::Frame: + case SelectionType::Graphic: + case SelectionType::Ole: + case SelectionType::DrawObject: + case SelectionType::DrawObjectEditMode: + case SelectionType::DbForm: + { + // #108205# Remember object's position. + Point aTmpPt = GetObjRect().TopLeft(); + + // Remember the anchor of the selected object before deletion. + std::unique_ptr pAnchor; + SwFlyFrame* pFly = GetSelectedFlyFrame(); + 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().GetContentAnchor()) + { + pAnchor.reset(new SwPosition(*pFormat->GetAnchor().GetContentAnchor())); + } + } + } + + // Group deletion of the object and its comment together. + mxDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr); + + DelSelectedObj(); + + if (pAnchor) + { + SwTextNode* pTextNode = pAnchor->nNode.GetNode().GetTextNode(); + if (pTextNode) + { + const SwTextField* pField( + pTextNode->GetFieldTextAttrAt(pAnchor->nContent.GetIndex(), true)); + if (pField + && dynamic_cast(pField->GetFormatField().GetField())) + { + // Remove the comment of the deleted object. + *GetCurrentShellCursor().GetPoint() = *pAnchor; + DelRight(); + } + } + } + + mxDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); + + // #108205# Set cursor to remembered position. + SetCursor(&aTmpPt); + + LeaveSelFrameMode(); + UnSelectFrame(); + OSL_ENSURE( !IsFrameSelected(), + " - should unmark all objects" ); + // leave draw mode, if necessary. + { + if (GetView().GetDrawFuncPtr()) + { + GetView().GetDrawFuncPtr()->Deactivate(); + GetView().SetDrawFuncPtr(nullptr); + } + if ( GetView().IsDrawMode() ) + { + GetView().LeaveDrawCreate(); + } + } + } + + // 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(); + 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(); + 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(); + 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,CRSR_SKIP_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(); + } + 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(); + 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(); + 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 000000000..14070c71e --- /dev/null +++ b/sw/source/uibase/wrtsh/move.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 +#include +#include +#include +#include +#include + +/** + Always: + - Reset of the cursor stack + - retrigger timer + - if applicable: GCAttr + + on selection + - SttSelect() + + else + - EndSelect() + */ + +const 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( sal_uInt16 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( sal_uInt16 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; + } + if( MoveTable( GotoCurrTable, fnTableStart ) || bDontMoveRegion ) + { + if ( pMoveTable ) + *pMoveTable = true; + 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; + } + // Regions ??? + return SwCursorShell::MoveRegion( GotoCurrRegionAndSkip, fnRegionStart ) || + SwCursorShell::SttEndDoc(true); +} + +bool SwWrtShell::GoEnd(bool bKeepArea, const bool *pMoveTable) +{ + if ( pMoveTable && *pMoveTable ) + return MoveTable( GotoCurrTable, fnTableEnd ); + + 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.IsInside(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.IsInside( 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) +{ + 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::GotoRegion( const OUString& 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 ) +{ + SwPosition aPos = *GetCursor()->GetPoint(); + bool bRet = SwCursorShell::GotoRefMark(rRefMark, nSubType, nSeqNo); + 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); +} + +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 000000000..c43992662 --- /dev/null +++ b/sw/source/uibase/wrtsh/navmgr.cxx @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// 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()) { + /* 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()) { + // 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); + + // show the Navigation toolbar + css::uno::Reference< css::frame::XFrame > xFrame = + m_rMyShell.GetView().GetViewFrame()->GetFrame().GetFrameInterface(); + if (xFrame.is()) + { + css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager"); + + aValue >>= xLayoutManager; + if (xLayoutManager.is()) + { + const OUString sResourceURL( "private:resource/toolbar/navigationobjectbar" ); + css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL); + if (!xUIElement.is()) + { + xLayoutManager->createElement( sResourceURL ); + xLayoutManager->showElement( sResourceURL ); + } + } + } + } + + 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 000000000..a5c1ecbb7 --- /dev/null +++ b/sw/source/uibase/wrtsh/select.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace com::sun::star::util { + struct SearchOptions2; +} + +using namespace ::com::sun::star::util; + +static 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 ); + SwWordCountWrapper *pWrdCnt = static_cast(GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId())); + if (pWrdCnt) + pWrdCnt->UpdateCounts(); +} + +bool SwWrtShell::SelNearestWrd() +{ + SwMvContext aMvContext(this); + if( !IsInWord() && !IsEndWrd() && !IsStartWord() ) + PrvWrd(); + if( IsEndWrd() ) + Left(CRSR_SKIP_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::unique_ptr pStartPos; + std::unique_ptr pEndPos; + SwShellCursor* pTmpCursor = nullptr; + + // Query these early, before we move the cursor. + bool bHasWholeTabSelection = HasWholeTabSelection(); + bool bIsCursorInTable = IsCursorInTable(); + + if (!bHasWholeTabSelection) + { + if ( IsSelection() && IsCursorPtAtEnd() ) + SwapPam(); + pTmpCursor = getShellCursor( false ); + if( pTmpCursor ) + { + pStartPos.reset(new SwPosition( *pTmpCursor->GetPoint() )); + pEndPos.reset(new SwPosition( *pTmpCursor->GetMark() )); + } + Push(); + bool bIsFullSel = !MoveSection( GoCurrSection, fnSectionStart); + SwapPam(); + bIsFullSel &= !MoveSection( GoCurrSection, fnSectionEnd); + Pop(SwCursorShell::PopMode::DeleteCurrent); + GoStart(true, &bMoveTable, false, !bIsFullSel); + } + else + { + EnterStdMode(); + SttEndDoc(true); + } + SttSelect(); + GoEnd(true, &bMoveTable); + + bool bNeedsExtendedSelectAll = StartsWithTable(); + + // If the cursor was in a table, then we only need the extended select + // all if the whole table is already selected, to still allow selecting + // only a single cell or a single table before selecting the whole + // document. + if (bNeedsExtendedSelectAll && bIsCursorInTable) + bNeedsExtendedSelectAll = bHasWholeTabSelection; + + if (bNeedsExtendedSelectAll) + { + // Disable table cursor to make sure getShellCursor() returns m_pCurrentCursor, not m_pTableCursor. + if (IsTableMode()) + TableCursorToCursor(); + // Do the extended select all on m_pCurrentCursor. + ExtendedSelectAll(/*bFootnotes =*/ false); + } + + SwDoc *pDoc = GetDoc(); + if ( pDoc ) + { + pDoc->SetPrepareSelAll(); + } + + if( pStartPos ) + { + 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() < *pEndPos || + ( *pStartPos == *pTmpCursor->GetMark() && + *pEndPos == *pTmpCursor->GetPoint() ) ) && !bNeedsExtendedSelectAll) + SwCursorShell::SttEndDoc(false); + } + } + } + EndSelect(); + LockView( bLockedView ); +} + +// Description: Text search + +sal_uLong 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_uLong nRet = Find_Text(rSearchOpt, bSearchInNotes, eStt, eEnd, bCancel, eFlags, bReplace); + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + return nRet; +} + +// Description: search for templates + +sal_uLong 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_uLong nRet = FindFormat(pColl ? *pColl : GetDfltTextFormatColl(), + eStt,eEnd, bCancel, eFlags, pReplaceColl); + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + return nRet; +} + +// search for attributes + +sal_uLong 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_uLong nRet = FindAttrs(rFindSet, bNoColls, eStart, eEnd, bCancel, eFlags, pSearchOpt, pReplaceSet); + + if(bCancel) + { + Undo(); + nRet = ULONG_MAX; + } + 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. + +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); +} + +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 + +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 + +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()->nContent.GetIndex()); + OUString aSelEnd = OUString::number(pCursor->End()->nContent.GetIndex()); + + 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(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 ) + { + // 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,CRSR_SKIP_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 ); +} + +// 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 ) +{ + 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(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(); +} + +bool SwWrtShell::ToggleBlockMode() +{ + m_bBlockMode ? LeaveBlockMode(): EnterBlockMode(); + Invalidate(); + return !m_bBlockMode; +} + +bool SwWrtShell::ToggleExtMode() +{ + m_bExtMode ? LeaveExtMode() : EnterExtMode(); + Invalidate(); + return !m_bExtMode; +} + +// 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,CRSR_SKIP_CHARS); + SwFEShell::Delete(); + 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,CRSR_SKIP_CHARS); + SwFEShell::Delete(); + 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 000000000..44e7391ba --- /dev/null +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -0,0 +1,1990 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -> #111827# +#include +#include +// <- #111827# + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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); +} + +} + +#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 )) + 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() ) + { + 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; + + typedef svl::Items CharItems; + SfxItemSet aCharAttrSet(GetAttrPool(), CharItems{}); + + if( bHasSel || ( !m_bIns && SelectHiddenRange() ) ) + { + // 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); + } + + // tdf#79717 Save character formatting of the start of the selection + const SwPosition *pStart = GetCursor()->Start(); + SwPaM aPaM(pStart->nNode.GetNode(), pStart->nContent.GetIndex(), + pStart->nNode.GetNode(), pStart->nContent.GetIndex() + 1); + GetPaMAttr(&aPaM, aCharAttrSet); + + StartUndo(SwUndoId::REPLACE, &aRewriter); + bStarted = true; + Push(); + bDeleted = DelRight(); + 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 ); + + if( bDeleted ) + { + // tdf#79717 Restore formatting of the deleted selection + SwPosition* pEnd = GetCursor()->Start(); + SwPaM aPaM(pEnd->nNode.GetNode(), pEnd->nContent.GetIndex() - rStr.getLength(), + pEnd->nNode.GetNode(), pEnd->nContent.GetIndex()); + + SetAttrSet(aCharAttrSet, SetAttrMode::DEFAULT, &aPaM); + } + + if( bStarted ) + { + EndUndo(); + EndAllAction(); + } +} + +// Maximum height limit not possible, because the maximum height +// of the current frame can not be obtained. + +void SwWrtShell::Insert( 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(567); + aSz.setHeight( 567); + pFrameMgr->SetSize( aSz ); + } + else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT ) + bSetGrfSize = false; + + pFrameMgr->SetHeightSizeType(SwFrameSize::Fixed); + } + + // Insert the graphic + SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet()); + if ( bOwnMgr ) + pFrameMgr->UpdateAttrMgr(); + + if( bSetGrfSize ) + { + Size aGrfSize, aBound = GetGraphicDefaultSize(); + 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: + { + 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); + OString aCmd = OStringLiteral(".uno:") + pSlot->GetUnoName(); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr pDlg(pFact->CreateInsertObjectDialog(GetFrameWeld(mxDoc->GetDocShell()), + OUString::fromUtf8( 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::makeAny( 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::makeAny( false ) ); + xProps->setPropertyValue("DisableComplexChartTypes", + uno::makeAny( 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( long nVerb ) +{ + if ( GetCntType() == CNT_OLE && + !GetView().GetViewFrame()->GetFrame().IsInPlace() ) + { + 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() && !SotExchange::IsChart(xRef->getClassID())) + return; + + SfxInPlaceClient* pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() ); + if ( !pCli ) + pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef ); + + static_cast(pCli)->SetInDoVerb( true ); + + CalcAndSetScale( xRef ); + pCli->DoVerb( nVerb ); + + static_cast(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 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 + 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 + { + aArea.Width ( long( aArea.Width() / pCli->GetScaleWidth() ) ); + aArea.Height( long( aArea.Height() / pCli->GetScaleHeight() ) ); + } + + 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& oPgNum ) +{ + 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() +{ + ResetCursorStack(); + if( CanInsert() ) + { + if(HasSelection()) + DelRight(); + + const sal_Unicode cIns = 0x0A; + SvxAutoCorrect* pACorr = lcl_IsAutoCorr(); + if( pACorr ) + AutoCorrect( *pACorr, cIns ); + else + SwWrtShell::Insert( OUString( cIns ) ); + } +} + +// Insert hard column break; +// Selections will be overwritten + +void SwWrtShell::InsertColumnBreak() +{ + SwActContext aActContext(this); + ResetCursorStack(); + if( CanInsert() ) + { + 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); + } +} + +// Insert footnote +// rStr - optional footnote mark + +void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit ) +{ + ResetCursorStack(); + if( CanInsert() ) + { + 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(CRSR_SKIP_CHARS, false, 1, false ); + GotoFootnoteText(); + } + m_aNavigationMgr.addEntry(aPos); + } +} + +// SplitNode; also, because +// - of deleting selected content; +// - of reset of the Cursorstack if necessary. + +void SwWrtShell::SplitNode( bool bAutoFormat ) +{ + ResetCursorStack(); + if( CanInsert() ) + { + SwActContext aActContext(this); + + m_rView.GetEditWin().FlushInBuffer(); + bool bHasSel = HasSelection(); + if( bHasSel ) + { + StartUndo( SwUndoId::INSERT ); + DelRight(); + } + + SwFEShell::SplitNode( bAutoFormat ); + if( bHasSel ) + EndUndo( SwUndoId::INSERT ); + } +} + +// 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): +// - is false, if is true +// - is false, if is false +// Behavior of method is determined by the current situation at the current +// cursor position in the document. +void SwWrtShell::NumOrBulletOn(bool bNum) +{ + // determine numbering rule found at current cursor position in the document. + const SwNumRule* pCurRule = GetNumRuleAtCurrCursorPos(); + + StartUndo(SwUndoId::NUMORNONUM); + + const SwNumRule * pNumRule = pCurRule; + + // - activate outline rule respectively turning on outline rule for + // current text node. But, only for turning on a numbering ( == 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 == 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 . If not, set 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(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()->nNode); + 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(), + " - paragraph style with outline rule, but no outline level" ); + if ( pColl->IsAssignedToListLevelOfOutlineStyle() && + pCollRule->Get( static_cast(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 == 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( static_cast(nActivateOutlineLvl) ).GetNumberingType() + == SVX_NUM_NUMBER_NONE ) + { + // activate outline numbering, because from the precondition + // it's known, that == 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(), + " - paragraph style with outline rule, but no outline level" ); + if ( pColl->IsAssignedToListLevelOfOutlineStyle() && + pCollRule->Get( static_cast(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()->nNode); + + 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(static_cast(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(nLevel))); + aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL); + // #i93908# clear suffix for bullet lists + aFormat.SetPrefix(OUString()); + aFormat.SetSuffix(OUString()); + } + aNumRule.Set(static_cast(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()->nNode); + const SwTwips nWidthOfTabs = pTextNode + ? pTextNode->GetWidthOfLeadingTabs() + : 0; + GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace( *GetCursor()->GetPoint() ); + + const bool bHtml = dynamic_cast( 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.SetPrefix(OUString()); + aFormat.SetSuffix(OUString()); + } + + // #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) + { + if (pCurNumRule->IsOutlineRule()) + { + SwNumRule aNumRule(*pCurNumRule); + + SwTextNode * pTextNode = + sw::GetParaPropsNode(*GetLayout(), GetCursor()->GetPoint()->nNode); + + if (pTextNode) + { + int nLevel = pTextNode->GetActualListLevel(); + + if (nLevel < 0) + nLevel = 0; + + if (nLevel >= MAXLEVEL) + nLevel = MAXLEVEL - 1; + + SwNumFormat aFormat(aNumRule.Get(static_cast(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(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; + } + sal_uInt32 nCheckStatus = 0; + if (svx::checkForSelectedFontWork( GetDrawView(), nCheckStatus )) + { + nCnt |= SelectionType::FontWork; + } + } + + return nCnt; + } + + nCnt = static_cast(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()->nNode); + + 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(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(const OUString &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( ); + SfxItemSet aCoreSet( + GetAttrPool(), + 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_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>{}); + 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 == aCoreSet.GetItemState(nWhich) && + SfxItemState::SET == rStyleSet.GetItemState(nWhich)) + { + aCoreSet.ClearItem(nWhich); + bReset = true; + } + } + } + StartAction(); + if(bReset) + { + ResetAttr( std::set(), 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()) + { + 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(); + } + 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 + SET_CURR_SHELL( this ); + + SetSfxViewShell( static_cast(&rShell) ); + SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) ); + + // place the cursor on the first field... + IFieldmark *pBM = nullptr; + if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=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 + SET_CURR_SHELL( this ); + SetSfxViewShell( static_cast(&rShell) ); + SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) ); + + // place the cursor on the first field... + IFieldmark *pBM = nullptr; + if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) { + GotoFieldmark(pBM); + } +} + +SwWrtShell::~SwWrtShell() +{ + SET_CURR_SHELL( this ); + while(IsModePushed()) + PopMode(); + while(PopCursor(false)) + ; + SwTransferable::ClearSelection( *this ); +} + +bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete) +{ + bool bRet = SwCursorShell::Pop(eDelete); + 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( + const OUString& 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.isEmpty() || 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 ) + { + SvxULSpaceItem aUL(bHeader ? 0 : MM50, bHeader ? MM50 : 0, RES_UL_SPACE ); + SwFrameFormat* pFormat = bHeader ? + const_cast(rMaster.GetHeader().GetHeaderFormat()) : + const_cast(rMaster.GetFooter().GetFooterFormat()); + pFormat->SetFormatAttr( aUL ); + } + } + if( bChgd ) + { + ChgPageDesc( nFrom, aDesc ); + + if( !bCursorSet && bOn ) + { + if ( !IsHeaderFooterEdit() ) + ToggleHeaderFooterEdit(); + bCursorSet = SetCursorInHdFt( + rStyleName.isEmpty() ? 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(rFieldMgr.GetCurField()); + bool bNew = !(pPostIt && pPostIt->GetTyp()->Which() == SwFieldIds::Postit); + if (bNew || GetView().GetPostItMgr()->IsAnswer()) + { + const SvxPostItAuthorItem* pAuthorItem = rReq.GetArg(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(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::unique_ptr pAnchor; + 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().GetContentAnchor()) + { + pAnchor.reset(new SwPosition(*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) + { + *GetCurrentShellCursor().GetPoint() = *pAnchor; + SwFrameFormat* pFormat = pFly->GetFormat(); + if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) + { + Right(CRSR_SKIP_CELLS, /*bSelect=*/true, 1, /*bBasicCall=*/false, /*bVisual=*/true); + } + else if (pFormat && pFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_CHAR) + { + aData.m_pAnnotationRange.reset(new SwPaM(*GetCurrentShellCursor().Start(), + *GetCurrentShellCursor().End())); + } + } + } + + rFieldMgr.InsertField( aData ); + + Push(); + SwCursorShell::Left(1, CRSR_SKIP_CHARS); + pPostIt = static_cast(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() ) ); + } +} + +/* 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 000000000..5dc536a95 --- /dev/null +++ b/sw/source/uibase/wrtsh/wrtsh2.cxx @@ -0,0 +1,606 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +void SwWrtShell::Insert(SwField const& rField, SwPaM* pAnnotationRange) +{ + ResetCursorStack(); + if(!CanInsert()) + return; + StartAllAction(); + + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, rField.GetDescription()); + + StartUndo(SwUndoId::INSERT, &aRewriter); + + bool bDeleted = false; + std::unique_ptr pAnnotationTextRange; + if (pAnnotationRange) + { + pAnnotationTextRange.reset(new SwPaM(*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()->nNode.GetNode().GetContentNode()), 0 ); + KillPams(); + if ( !IsEndOfPara() ) + { + EndPara(); + } + const SwPosition rEndPos( *GetCurrentShellCursor().GetPoint() ); + pAnnotationTextRange.reset(new SwPaM( rStartPos, rEndPos )); + } + else + { + NormalizePam( false ); + const SwPaM& rCurrPaM = GetCurrentShellCursor(); + pAnnotationTextRange.reset(new SwPaM( *rCurrPaM.GetPoint(), *rCurrPaM.GetMark() )); + ClearMark(); + } + } + else + { + bDeleted = DelRight(); + } + } + + SwEditShell::Insert2(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. + SwIndex& rRangeStart = pAnnotationTextRange->Start()->nContent; + if (rRangeStart.GetIndex() > 0) + --rRangeStart; + } + IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess(); + pMarksAccess->makeAnnotationMark( *pAnnotationTextRange, OUString() ); + } + pAnnotationTextRange.reset(); + } + + EndUndo(); + EndAllAction(); +} + +// Start the field update + +void SwWrtShell::UpdateInputFields( SwInputFieldList* pLst ) +{ + // Go through the list of fields and updating + std::unique_ptr pTmp; + if (!pLst) + { + pTmp.reset(new SwInputFieldList( this )); + pLst = pTmp.get(); + } + + const size_t nCnt = pLst->Count(); + if(nCnt) + { + 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(pField)); + SwSetExpField *const pSetExpField(dynamic_cast(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 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 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 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 ) +{ + // cross reference field must not be selected because it moves the cursor + if (SwFieldIds::GetRef != rField.GetTyp()->Which()) + { + StartAllAction(); + Right( CRSR_SKIP_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(&rField); + const OUString sText( rField.GetPar2() ); + OUString sRet( sText ); + ExecMacro( pField->GetSvxMacro(), &sRet ); + + // return value changed? + if( sRet != sText ) + { + StartAllAction(); + const_cast(rField).SetPar2( sRet ); + rField.GetTyp()->UpdateFields(); + EndAllAction(); + } + } + break; + + case SwFieldIds::GetRef: + StartAllAction(); + SwCursorShell::GotoRefMark( static_cast(rField).GetSetRefName(), + static_cast(rField).GetSubType(), + static_cast(rField).GetSeqNo() ); + EndAllAction(); + break; + + case SwFieldIds::Input: + { + const SwInputField* pInputField = dynamic_cast(&rField); + if ( pInputField == nullptr ) + { + StartInputFieldDlg(const_cast(&rField), false, false, GetView().GetFrameWeld()); + } + } + break; + + case SwFieldIds::SetExp: + if( static_cast(rField).GetInputFlag() ) + StartInputFieldDlg(const_cast(&rField), false, false, GetView().GetFrameWeld()); + break; + case SwFieldIds::Dropdown : + StartDropDownFieldDlg(const_cast(&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 ) +{ + 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(pTextAttr)->SetVisited( true ); + const_cast(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; +} + +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 ( dynamic_cast( &rVSh) == nullptr ) + 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("#")) + { + rVSh.GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED, rURL.toUtf8().getStr()); + return; + } + + //A CursorShell is always a WrtShell + SwWrtShell &rSh = static_cast(rVSh); + + SwDocShell* pDShell = rSh.GetView().GetDocShell(); + OSL_ENSURE( pDShell, "No DocShell?!"); + OUString sTargetFrame(rTargetFrameName); + if (sTargetFrame.isEmpty() && pDShell) + { + using namespace ::com::sun::star; + uno::Reference xDPS( + pDShell->GetModel(), uno::UNO_QUERY_THROW); + uno::Reference xDocProps + = xDPS->getDocumentProperties(); + sTargetFrame = xDocProps->getDefaultTarget(); + } + + OUString sReferer; + if( pDShell && pDShell->GetMedium() ) + sReferer = pDShell->GetMedium()->GetName(); + SfxViewFrame* pViewFrame = rSh.GetView().GetViewFrame(); + SfxFrameItem aView( SID_DOCFRAME, pViewFrame ); + 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" ); + + const SfxPoolItem* aArr[] = { + &aName, + &aNewView, /*&aSilent,*/ + &aReferer, + &aView, &aTargetFrameName, + &aBrowse, + nullptr + }; + + pViewFrame->GetDispatcher()->GetBindings()->Execute( SID_OPENDOC, aArr, + SfxCallMode::ASYNCHRON|SfxCallMode::RECORD ); +} + +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 = rBkmk.GetURL().getToken(0, '#') + + OUStringChar(sfx2::cTokenSeparator) + + OUStringChar(sfx2::cTokenSeparator) + + rBkmk.GetURL().getToken(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 000000000..1fd1ce2cd --- /dev/null +++ b/sw/source/uibase/wrtsh/wrtsh3.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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::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( 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 000000000..8009ce980 --- /dev/null +++ b/sw/source/uibase/wrtsh/wrtsh4.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +// 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,CRSR_SKIP_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,CRSR_SKIP_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,CRSR_SKIP_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,CRSR_SKIP_CHARS) ) + break; + bRet = IsStartWord(); + } + else + bRet = true; + } + ClearMark(); + Combine(); + return bRet; +} + +// #i92468# +// method code of before fix for issue i72162 +bool SwWrtShell::NxtWrdForDelete() +{ + if ( IsEndPara() ) + { + if ( !SwCursorShell::Right(1,CRSR_SKIP_CHARS) ) + { + Pop(SwCursorShell::PopMode::DeleteCurrent); + return false; + } + return true; + } + Push(); + ClearMark(); + if ( !GoNextWord() ) + { + SwCursorShell::MovePara( GoCurrPara, fnParaEnd ); + } + ClearMark(); + Combine(); + return true; +} + +// method code of before fix for issue i72162 +bool SwWrtShell::PrvWrdForDelete() +{ + if ( IsSttPara() ) + { + if ( !SwCursorShell::Left(1,CRSR_SKIP_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,CRSR_SKIP_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,CRSR_SKIP_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; +} + +/* 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 000000000..1e92006a2 --- /dev/null +++ b/sw/source/uibase/wrtsh/wrtundo.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 +#include +#include +#include +#include +#include +#include +#include + +// 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 ) +{ + // #105332# save current state of DoesUndo() + bool bSaveDoesUndo = DoesUndo(); + + StartAllAction(); + switch (eDoType) + { + case UNDO: + DoUndo(false); // #i21739# + // Reset modes + EnterStdMode(); + SwEditShell::Undo(nCnt); + 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; + const char* 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).append("\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: */ -- cgit v1.2.3