diff options
Diffstat (limited to 'sw/source/uibase/uno')
-rw-r--r-- | sw/source/uibase/uno/SwXDocumentSettings.cxx | 1709 | ||||
-rw-r--r-- | sw/source/uibase/uno/SwXDocumentSettings.hxx | 78 | ||||
-rw-r--r-- | sw/source/uibase/uno/SwXFilterOptions.cxx | 147 | ||||
-rw-r--r-- | sw/source/uibase/uno/dlelstnr.cxx | 134 | ||||
-rw-r--r-- | sw/source/uibase/uno/loktxdoc.cxx | 492 | ||||
-rw-r--r-- | sw/source/uibase/uno/unoatxt.cxx | 993 | ||||
-rw-r--r-- | sw/source/uibase/uno/unodefaults.cxx | 46 | ||||
-rw-r--r-- | sw/source/uibase/uno/unodefaults.hxx | 36 | ||||
-rw-r--r-- | sw/source/uibase/uno/unodispatch.cxx | 374 | ||||
-rw-r--r-- | sw/source/uibase/uno/unodoc.cxx | 93 | ||||
-rw-r--r-- | sw/source/uibase/uno/unomailmerge.cxx | 1168 | ||||
-rw-r--r-- | sw/source/uibase/uno/unomod.cxx | 976 | ||||
-rw-r--r-- | sw/source/uibase/uno/unomodule.cxx | 150 | ||||
-rw-r--r-- | sw/source/uibase/uno/unomodule.hxx | 74 | ||||
-rw-r--r-- | sw/source/uibase/uno/unotxdoc.cxx | 4816 | ||||
-rw-r--r-- | sw/source/uibase/uno/unotxvw.cxx | 1707 |
16 files changed, 12993 insertions, 0 deletions
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx new file mode 100644 index 0000000000..3e40989828 --- /dev/null +++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx @@ -0,0 +1,1709 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <utility> + +#include <o3tl/any.hxx> +#include "SwXDocumentSettings.hxx" +#include <comphelper/MasterPropertySetInfo.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/i18n/XForbiddenCharacters.hpp> +#include <com/sun/star/document/PrinterIndependentLayout.hpp> +#include <doc.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <docsh.hxx> +#include <fldupde.hxx> +#include <linkenum.hxx> +#include <sfx2/printer.hxx> +#include <editsh.hxx> +#include <unotxdoc.hxx> +#include <cmdid.h> +#include <unomod.hxx> +#include <vcl/svapp.hxx> +#include <svl/asiancfg.hxx> +#include <tools/stream.hxx> + +#include <cfgitems.hxx> +#include <dbmgr.hxx> + +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::i18n; + +namespace { + +enum SwDocumentSettingsPropertyHandles +{ + HANDLE_FORBIDDEN_CHARS, + HANDLE_LINK_UPDATE_MODE, + HANDLE_FIELD_AUTO_UPDATE, + HANDLE_CHART_AUTO_UPDATE, + HANDLE_ADD_PARA_TABLE_SPACING, + HANDLE_ADD_PARA_TABLE_SPACING_AT_START, + HANDLE_ALIGN_TAB_STOP_POSITION, + HANDLE_PRINTER_NAME, + HANDLE_PRINTER_SETUP, + HANDLE_PRINTER_PAPER, + HANDLE_IS_KERN_ASIAN_PUNCTUATION, + HANDLE_CHARACTER_COMPRESSION_TYPE, + HANDLE_APPLY_USER_DATA, + HANDLE_SAVE_THUMBNAIL, + HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS, + HANDLE_CURRENT_DATABASE_DATA_SOURCE, + HANDLE_CURRENT_DATABASE_COMMAND, + HANDLE_CURRENT_DATABASE_COMMAND_TYPE, + HANDLE_EMBEDDED_DATABASE_NAME, + HANDLE_SAVE_VERSION_ON_CLOSE, + HANDLE_UPDATE_FROM_TEMPLATE, + HANDLE_PRINTER_INDEPENDENT_LAYOUT, + HANDLE_IS_LABEL_DOC, + HANDLE_IS_ADD_FLY_OFFSET, + HANDLE_IS_ADD_VERTICAL_FLY_OFFSET, + HANDLE_IS_ADD_EXTERNAL_LEADING, + HANDLE_OLD_NUMBERING, + HANDLE_OUTLINELEVEL_YIELDS_NUMBERING, + /* Stampit It disable the print cancel button of the shown progress dialog. */ + HANDLE_ALLOW_PRINTJOB_CANCEL, + HANDLE_USE_FORMER_LINE_SPACING, + HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS, + HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, + HANDLE_USE_FORMER_OBJECT_POSITIONING, + HANDLE_USE_FORMER_TEXT_WRAPPING, + HANDLE_CHANGES_PASSWORD, + HANDLE_CONSIDER_WRAP_ON_OBJPOS, + HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, + HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, + HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, + HANDLE_TABLE_ROW_KEEP, + HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, + HANDLE_LOAD_READONLY, + HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, + HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES, + HANDLE_UNIX_FORCE_ZERO_EXT_LEADING, + HANDLE_USE_OLD_PRINTER_METRICS, + HANDLE_PROTECT_FORM, + HANDLE_MS_WORD_COMP_TRAILING_BLANKS, + HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, + HANDLE_TABS_RELATIVE_TO_INDENT, + HANDLE_RSID, + HANDLE_RSID_ROOT, + HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, + HANDLE_MODIFYPASSWORDINFO, + HANDLE_MATH_BASELINE_ALIGNMENT, + HANDLE_INVERT_BORDER_SPACING, + HANDLE_COLLAPSE_EMPTY_CELL_PARA, + HANDLE_SMALL_CAPS_PERCENTAGE_66, + HANDLE_TAB_OVERFLOW, + HANDLE_UNBREAKABLE_NUMBERINGS, + HANDLE_STYLES_NODEFAULT, + HANDLE_CLIPPED_PICTURES, + HANDLE_BACKGROUND_PARA_OVER_DRAWINGS, + HANDLE_EMBED_FONTS, + HANDLE_EMBED_USED_FONTS, + HANDLE_EMBED_LATIN_SCRIPT_FONTS, + HANDLE_EMBED_ASIAN_SCRIPT_FONTS, + HANDLE_EMBED_COMPLEX_SCRIPT_FONTS, + HANDLE_EMBED_SYSTEM_FONTS, + HANDLE_TAB_OVER_MARGIN, + HANDLE_TAB_OVER_SPACING, + HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, + HANDLE_SURROUND_TEXT_WRAP_SMALL, + HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, + HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE, + HANDLE_SUBTRACT_FLYS, + HANDLE_DISABLE_OFF_PAGE_POSITIONING, + HANDLE_EMPTY_DB_FIELD_HIDES_PARA, + HANDLE_CONTINUOUS_ENDNOTES, + HANDLE_PROTECT_BOOKMARKS, + HANDLE_PROTECT_FIELDS, + HANDLE_HEADER_SPACING_BELOW_LAST_PARA, + HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA, + HANDLE_GUTTER_AT_TOP, + HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND, + HANDLE_IMAGE_PREFERRED_DPI, + HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, + HANDLE_HYPHENATE_URLS, + HANDLE_DO_NOT_BREAK_WRAPPED_TABLES, + HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, + HANDLE_JUSTIFY_LINES_WITH_SHRINKING, + HANDLE_NO_NUMBERING_SHOW_FOLLOWBY, + HANDLE_DROP_CAP_PUNCTUATION, + HANDLE_USE_VARIABLE_WIDTH_NBSP, +}; + +} + +static rtl::Reference<MasterPropertySetInfo> lcl_createSettingsInfo() +{ + static PropertyInfo const aWriterSettingsInfoMap[] = + { + { OUString("ForbiddenCharacters"), HANDLE_FORBIDDEN_CHARS, cppu::UnoType<css::i18n::XForbiddenCharacters>::get(), 0}, + { OUString("LinkUpdateMode"), HANDLE_LINK_UPDATE_MODE, cppu::UnoType<sal_Int16>::get(), 0}, + { OUString("FieldAutoUpdate"), HANDLE_FIELD_AUTO_UPDATE, cppu::UnoType<bool>::get(), 0}, + { OUString("ChartAutoUpdate"), HANDLE_CHART_AUTO_UPDATE, cppu::UnoType<bool>::get(), 0}, + { OUString("AddParaTableSpacing"), HANDLE_ADD_PARA_TABLE_SPACING, cppu::UnoType<bool>::get(), 0}, + { OUString("AddParaTableSpacingAtStart"), HANDLE_ADD_PARA_TABLE_SPACING_AT_START, cppu::UnoType<bool>::get(), 0}, + { OUString("AlignTabStopPosition"), HANDLE_ALIGN_TAB_STOP_POSITION, cppu::UnoType<bool>::get(), 0}, + { OUString("PrinterName"), HANDLE_PRINTER_NAME, cppu::UnoType<OUString>::get(), 0}, + { OUString("PrinterSetup"), HANDLE_PRINTER_SETUP, cppu::UnoType< cppu::UnoSequenceType<sal_Int8> >::get(), 0}, + { OUString("PrinterPaperFromSetup"), HANDLE_PRINTER_PAPER, cppu::UnoType<bool>::get(), 0}, + { OUString("IsKernAsianPunctuation"), HANDLE_IS_KERN_ASIAN_PUNCTUATION, cppu::UnoType<bool>::get(), 0}, + { OUString("CharacterCompressionType"), HANDLE_CHARACTER_COMPRESSION_TYPE, cppu::UnoType<sal_Int16>::get(), 0}, + { OUString("ApplyUserData"), HANDLE_APPLY_USER_DATA, cppu::UnoType<bool>::get(), 0 }, + { OUString("SaveThumbnail"), HANDLE_SAVE_THUMBNAIL, cppu::UnoType<bool>::get(), 0 }, + { OUString("SaveGlobalDocumentLinks"), HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS, cppu::UnoType<bool>::get(), 0}, + { OUString("CurrentDatabaseDataSource"), HANDLE_CURRENT_DATABASE_DATA_SOURCE, cppu::UnoType<OUString>::get(), 0}, + { OUString("CurrentDatabaseCommand"), HANDLE_CURRENT_DATABASE_COMMAND, cppu::UnoType<OUString>::get(), 0}, + { OUString("CurrentDatabaseCommandType"), HANDLE_CURRENT_DATABASE_COMMAND_TYPE, cppu::UnoType<sal_Int32>::get(), 0}, + { OUString("EmbeddedDatabaseName"), HANDLE_EMBEDDED_DATABASE_NAME, cppu::UnoType<OUString>::get(), 0}, + { OUString("SaveVersionOnClose"), HANDLE_SAVE_VERSION_ON_CLOSE, cppu::UnoType<bool>::get(), 0}, + { OUString("UpdateFromTemplate"), HANDLE_UPDATE_FROM_TEMPLATE, cppu::UnoType<bool>::get(), 0}, + + { OUString("PrinterIndependentLayout"), HANDLE_PRINTER_INDEPENDENT_LAYOUT, cppu::UnoType<sal_Int16>::get(), 0}, + { OUString("IsLabelDocument"), HANDLE_IS_LABEL_DOC, cppu::UnoType<bool>::get(), 0}, + { OUString("AddFrameOffsets"), HANDLE_IS_ADD_FLY_OFFSET, cppu::UnoType<bool>::get(), 0}, + { OUString("AddVerticalFrameOffsets"), HANDLE_IS_ADD_VERTICAL_FLY_OFFSET, cppu::UnoType<bool>::get(), 0}, + { OUString("AddExternalLeading"), HANDLE_IS_ADD_EXTERNAL_LEADING, cppu::UnoType<bool>::get(), 0}, + { OUString("UseOldNumbering"), HANDLE_OLD_NUMBERING, cppu::UnoType<bool>::get(), 0}, + { OUString("OutlineLevelYieldsNumbering"), HANDLE_OUTLINELEVEL_YIELDS_NUMBERING, cppu::UnoType<bool>::get(), 0}, + /* Stampit It disable the print cancel button of the shown progress dialog. */ + { OUString("AllowPrintJobCancel"), HANDLE_ALLOW_PRINTJOB_CANCEL, cppu::UnoType<bool>::get(), 0}, + { OUString("UseFormerLineSpacing"), HANDLE_USE_FORMER_LINE_SPACING, cppu::UnoType<bool>::get(), 0}, + { OUString("AddParaSpacingToTableCells"), HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS, cppu::UnoType<bool>::get(), 0}, + { OUString("AddParaLineSpacingToTableCells"), HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, cppu::UnoType<bool>::get(), 0}, + { OUString("UseFormerObjectPositioning"), HANDLE_USE_FORMER_OBJECT_POSITIONING, cppu::UnoType<bool>::get(), 0}, + { OUString("UseFormerTextWrapping"), HANDLE_USE_FORMER_TEXT_WRAPPING, cppu::UnoType<bool>::get(), 0}, + { OUString("RedlineProtectionKey"), HANDLE_CHANGES_PASSWORD, cppu::UnoType< cppu::UnoSequenceType<sal_Int8> >::get(), 0}, + { OUString("ConsiderTextWrapOnObjPos"), HANDLE_CONSIDER_WRAP_ON_OBJPOS, cppu::UnoType<bool>::get(), 0}, + { OUString("IgnoreFirstLineIndentInNumbering"), HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, cppu::UnoType<bool>::get(), 0}, + { OUString("DoNotJustifyLinesWithManualBreak"), HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, cppu::UnoType<bool>::get(), 0}, + { OUString("DoNotResetParaAttrsForNumFont"), HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, cppu::UnoType<bool>::get(), 0}, + { OUString("TableRowKeep"), HANDLE_TABLE_ROW_KEEP, cppu::UnoType<bool>::get(), 0}, + { OUString("IgnoreTabsAndBlanksForLineCalculation"), HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, cppu::UnoType<bool>::get(), 0}, + { OUString("LoadReadonly"), HANDLE_LOAD_READONLY, cppu::UnoType<bool>::get(), 0}, + { OUString("DoNotCaptureDrawObjsOnPage"), HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, cppu::UnoType<bool>::get(), 0}, + { OUString("ClipAsCharacterAnchoredWriterFlyFrames"), HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES, cppu::UnoType<bool>::get(), 0}, + { OUString("UnxForceZeroExtLeading"), HANDLE_UNIX_FORCE_ZERO_EXT_LEADING, cppu::UnoType<bool>::get(), 0}, + { OUString("UseOldPrinterMetrics"), HANDLE_USE_OLD_PRINTER_METRICS, cppu::UnoType<bool>::get(), 0}, + { OUString("TabsRelativeToIndent"), HANDLE_TABS_RELATIVE_TO_INDENT, cppu::UnoType<bool>::get(), 0}, + { OUString("Rsid"), HANDLE_RSID, cppu::UnoType<sal_Int32>::get(), 0}, + { OUString("RsidRoot"), HANDLE_RSID_ROOT, cppu::UnoType<sal_Int32>::get(), 0}, + { OUString("ProtectForm"), HANDLE_PROTECT_FORM, cppu::UnoType<bool>::get(), 0}, + { OUString("MsWordCompTrailingBlanks"), HANDLE_MS_WORD_COMP_TRAILING_BLANKS, cppu::UnoType<bool>::get(), 0 }, + { OUString("MsWordCompMinLineHeightByFly"), HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, cppu::UnoType<bool>::get(), 0 }, + { OUString("TabAtLeftIndentForParagraphsInList"), HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, cppu::UnoType<bool>::get(), 0}, + { OUString("ModifyPasswordInfo"), HANDLE_MODIFYPASSWORDINFO, cppu::UnoType< cppu::UnoSequenceType<css::beans::PropertyValue> >::get(), 0}, + { OUString("MathBaselineAlignment"), HANDLE_MATH_BASELINE_ALIGNMENT, cppu::UnoType<bool>::get(), 0}, + { OUString("InvertBorderSpacing"), HANDLE_INVERT_BORDER_SPACING, cppu::UnoType<bool>::get(), 0}, + { OUString("CollapseEmptyCellPara"), HANDLE_COLLAPSE_EMPTY_CELL_PARA, cppu::UnoType<bool>::get(), 0}, + { OUString("SmallCapsPercentage66"), HANDLE_SMALL_CAPS_PERCENTAGE_66, cppu::UnoType<bool>::get(), 0}, + { OUString("TabOverflow"), HANDLE_TAB_OVERFLOW, cppu::UnoType<bool>::get(), 0}, + { OUString("UnbreakableNumberings"), HANDLE_UNBREAKABLE_NUMBERINGS, cppu::UnoType<bool>::get(), 0}, + { OUString("StylesNoDefault"), HANDLE_STYLES_NODEFAULT, cppu::UnoType<bool>::get(), 0}, + { OUString("ClippedPictures"), HANDLE_CLIPPED_PICTURES, cppu::UnoType<bool>::get(), 0}, + { OUString("BackgroundParaOverDrawings"), HANDLE_BACKGROUND_PARA_OVER_DRAWINGS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedFonts"), HANDLE_EMBED_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedOnlyUsedFonts"), HANDLE_EMBED_USED_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedLatinScriptFonts"), HANDLE_EMBED_LATIN_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedAsianScriptFonts"), HANDLE_EMBED_ASIAN_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedComplexScriptFonts"), HANDLE_EMBED_COMPLEX_SCRIPT_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("EmbedSystemFonts"), HANDLE_EMBED_SYSTEM_FONTS, cppu::UnoType<bool>::get(), 0}, + { OUString("TabOverMargin"), HANDLE_TAB_OVER_MARGIN, cppu::UnoType<bool>::get(), 0}, + { OUString("TabOverSpacing"), HANDLE_TAB_OVER_SPACING, cppu::UnoType<bool>::get(), 0}, + { OUString("TreatSingleColumnBreakAsPageBreak"), HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, cppu::UnoType<bool>::get(), 0}, + { OUString("SurroundTextWrapSmall"), HANDLE_SURROUND_TEXT_WRAP_SMALL, cppu::UnoType<bool>::get(), 0}, + { OUString("ApplyParagraphMarkFormatToNumbering"), HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, cppu::UnoType<bool>::get(), 0}, + { OUString("PropLineSpacingShrinksFirstLine"), HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE, cppu::UnoType<bool>::get(), 0}, + { OUString("SubtractFlysAnchoredAtFlys"), HANDLE_SUBTRACT_FLYS, cppu::UnoType<bool>::get(), 0}, + { OUString("DisableOffPagePositioning"), HANDLE_DISABLE_OFF_PAGE_POSITIONING, cppu::UnoType<bool>::get(), 0}, + { OUString("EmptyDbFieldHidesPara"), HANDLE_EMPTY_DB_FIELD_HIDES_PARA, cppu::UnoType<bool>::get(), 0 }, + { OUString("ContinuousEndnotes"), HANDLE_CONTINUOUS_ENDNOTES, cppu::UnoType<bool>::get(), 0 }, + { OUString("ProtectBookmarks"), HANDLE_PROTECT_BOOKMARKS, cppu::UnoType<bool>::get(), 0 }, + { OUString("ProtectFields"), HANDLE_PROTECT_FIELDS, cppu::UnoType<bool>::get(), 0 }, + { OUString("HeaderSpacingBelowLastPara"), HANDLE_HEADER_SPACING_BELOW_LAST_PARA, cppu::UnoType<bool>::get(), 0 }, + { OUString("FrameAutowidthWithMorePara"), HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA, cppu::UnoType<bool>::get(), 0 }, + { OUString("GutterAtTop"), HANDLE_GUTTER_AT_TOP, cppu::UnoType<bool>::get(), 0 }, + { OUString("FootnoteInColumnToPageEnd"), HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND, cppu::UnoType<bool>::get(), 0 }, + { OUString("ImagePreferredDPI"), HANDLE_IMAGE_PREFERRED_DPI, cppu::UnoType<sal_Int32>::get(), 0 }, + { OUString("AutoFirstLineIndentDisregardLineSpace"), HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, cppu::UnoType<bool>::get(), 0 }, + { OUString("HyphenateURLs"), HANDLE_HYPHENATE_URLS, cppu::UnoType<bool>::get(), 0 }, + { OUString("DoNotBreakWrappedTables"), HANDLE_DO_NOT_BREAK_WRAPPED_TABLES, cppu::UnoType<bool>::get(), 0 }, + { OUString("AllowTextAfterFloatingTableBreak"), HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, cppu::UnoType<bool>::get(), 0 }, + { OUString("JustifyLinesWithShrinking"), HANDLE_JUSTIFY_LINES_WITH_SHRINKING, cppu::UnoType<bool>::get(), 0 }, + { OUString("NoNumberingShowFollowBy"), HANDLE_NO_NUMBERING_SHOW_FOLLOWBY, cppu::UnoType<bool>::get(), 0 }, + { OUString("DropCapPunctuation"), HANDLE_DROP_CAP_PUNCTUATION, cppu::UnoType<bool>::get(), 0 }, + { OUString("UseVariableWidthNBSP"), HANDLE_USE_VARIABLE_WIDTH_NBSP, cppu::UnoType<bool>::get(), 0 }, + +/* + * As OS said, we don't have a view when we need to set this, so I have to + * find another solution before adding them to this property set - MTG + { OUString("IsGridVisible"), HANDLE_IS_GRID_VISIBLE, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("IsSnapToGrid"), HANDLE_IS_SNAP_TO_GRID, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("IsSynchroniseAxes"), HANDLE_IS_SYNCHRONISE_AXES, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("HorizontalGridResolution"), HANDLE_HORIZONTAL_GRID_RESOLUTION, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { OUString("HorizontalGridSubdivision"), HANDLE_HORIZONTAL_GRID_SUBDIVISION, cppu::UnoType<sal_Int16>::get(), 0, 0}, + { OUString("VerticalGridResolution"), HANDLE_VERTICAL_GRID_RESOLUTION, cppu::UnoType<sal_Int32>::get(), 0, 0}, + { OUString("VerticalGridSubdivision"), HANDLE_VERTICAL_GRID_SUBDIVISION, cppu::UnoType<sal_Int16>::get(), 0, 0}, + + { OUString("ShowParagraphEnd"), HANDLE_SHOW_PARAGRAPH_END, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowOptionalHyphens"), HANDLE_SHOW_OPTIONAL_HYPHENS, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowSpaces"), HANDLE_SHOW_SPACES, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowTabs"), HANDLE_SHOW_TABS, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowBreaks"), HANDLE_SHOW_BREAKS, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowHiddenText"), HANDLE_SHOW_HIDDEN_TEXT, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowHiddenParagraphs"), HANDLE_SHOW_HIDDEN_PARAGRAPHS, cppu::UnoType<bool>::get(), 0, 0}, + + { OUString("ShowTextLimitGuide"), HANDLE_SHOW_TEXT_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowTableLimitGuide"), HANDLE_SHOW_TABLE_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowSectionLimitGuide"), HANDLE_SHOW_SECTION_LIMIT_GUIDE, cppu::UnoType<bool>::get(), 0, 0}, + { OUString("ShowGuidesWhileMoving"), HANDLE_SHOW_GUIDES_WHILE_MOVING, cppu::UnoType<bool>::get(), 0, 0}, +*/ + { OUString(), 0, css::uno::Type(), 0} + }; + return new MasterPropertySetInfo ( aWriterSettingsInfoMap ); +} + +SwXDocumentSettings::SwXDocumentSettings ( SwXTextDocument * pModel ) +: MasterPropertySet ( lcl_createSettingsInfo().get(), + &Application::GetSolarMutex () ) +, mpModel ( pModel ) +, mpDocSh ( nullptr ) +, mpDoc ( nullptr ) +, mpPrinter( nullptr ) +, mbPreferPrinterPapersize( false ) +{ + registerSlave ( new SwXPrintSettings ( SwXPrintSettingsType::Document, mpModel->GetDocShell()->GetDoc() ) ); +} + +SwXDocumentSettings::~SwXDocumentSettings() + noexcept +{ +} + +Any SAL_CALL SwXDocumentSettings::queryInterface( const Type& rType ) +{ + return ::cppu::queryInterface(rType, + // OWeakObject interfaces + static_cast<XInterface*>(static_cast<OWeakObject*>(this)), + static_cast<XWeak*>(this), + // my own interfaces + static_cast<XPropertySet*>(this), + static_cast<XPropertyState*>(this), + static_cast<XMultiPropertySet*>(this), + static_cast<XServiceInfo*>(this), + static_cast<XTypeProvider*>(this)); +} +void SwXDocumentSettings::acquire () + noexcept +{ + OWeakObject::acquire(); +} +void SwXDocumentSettings::release () + noexcept +{ + OWeakObject::release(); +} + +uno::Sequence< uno::Type > SAL_CALL SwXDocumentSettings::getTypes( ) +{ + static const uno::Sequence< uno::Type > aTypes { + // from MasterPropertySet + cppu::UnoType<XPropertySet>::get(), + cppu::UnoType<XPropertyState>::get(), + cppu::UnoType<XMultiPropertySet>::get(), + cppu::UnoType<XServiceInfo>::get(), + cppu::UnoType<XTypeProvider>::get(), + }; + return aTypes; +} + +uno::Sequence< sal_Int8 > SAL_CALL SwXDocumentSettings::getImplementationId( ) +{ + return css::uno::Sequence<sal_Int8>(); +} + +void SwXDocumentSettings::_preSetValues () +{ + mpDocSh = mpModel->GetDocShell(); + if (nullptr == mpDocSh) + throw UnknownPropertyException(); + + mpDoc = mpDocSh->GetDoc(); + if (nullptr == mpDoc) + throw UnknownPropertyException(); +} + +void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue ) +{ + if (rInfo.mnAttributes & PropertyAttribute::READONLY) + throw PropertyVetoException ("Property is read-only: " + rInfo.maName); + + switch( rInfo.mnHandle ) + { + case HANDLE_FORBIDDEN_CHARS: + break; + case HANDLE_LINK_UPDATE_MODE: + { + sal_Int16 nMode = 0; + rValue >>= nMode; + switch (nMode) + { + case NEVER: + case MANUAL: + case AUTOMATIC: + case GLOBALSETTING: + break; + default: + throw IllegalArgumentException(); + } + mpDoc->getIDocumentSettingAccess().setLinkUpdateMode(nMode); + } + break; + case HANDLE_FIELD_AUTO_UPDATE: + { + bool bUpdateField = *o3tl::doAccess<bool>(rValue); + SwFieldUpdateFlags nFlag = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true); + mpDoc->getIDocumentSettingAccess().setFieldUpdateFlags( bUpdateField ? + nFlag == AUTOUPD_FIELD_AND_CHARTS ? + AUTOUPD_FIELD_AND_CHARTS : + AUTOUPD_FIELD_ONLY : + AUTOUPD_OFF ); + } + break; + case HANDLE_CHART_AUTO_UPDATE: + { + bool bUpdateChart = *o3tl::doAccess<bool>(rValue); + SwFieldUpdateFlags nFlag = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true); + mpDoc->getIDocumentSettingAccess().setFieldUpdateFlags( (nFlag == AUTOUPD_FIELD_ONLY || nFlag == AUTOUPD_FIELD_AND_CHARTS ) ? + bUpdateChart ? + AUTOUPD_FIELD_AND_CHARTS : + AUTOUPD_FIELD_ONLY : + AUTOUPD_OFF ); + } + break; + case HANDLE_ADD_PARA_TABLE_SPACING: + { + bool bParaSpace = false; + rValue >>= bParaSpace; + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX, bParaSpace ); + } + break; + case HANDLE_ADD_PARA_TABLE_SPACING_AT_START: + { + bool bParaSpacePage = false; + rValue >>= bParaSpacePage; + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES, bParaSpacePage ); + } + break; + case HANDLE_ALIGN_TAB_STOP_POSITION: + { + bool bAlignTab = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_COMPAT, bAlignTab); + } + break; + case HANDLE_PRINTER_NAME: + { + //the printer must be created + OUString sPrinterName; + if( !(rValue >>= sPrinterName) ) + throw IllegalArgumentException(); + + if( !mpPrinter && !sPrinterName.isEmpty() && mpDocSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ) + { + SfxPrinter* pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( true ); + if ( pPrinter->GetName() != sPrinterName ) + { + VclPtrInstance<SfxPrinter> pNewPrinter( pPrinter->GetOptions().Clone(), sPrinterName ); + assert (! pNewPrinter->isDisposed() ); + if( pNewPrinter->IsKnown() ) + { + // set printer only once; in _postSetValues + mpPrinter = pNewPrinter; + } + else + { + pNewPrinter.disposeAndClear(); + } + } + } + + } + break; + case HANDLE_PRINTER_SETUP: + { + Sequence < sal_Int8 > aSequence; + if ( !(rValue >>= aSequence) ) + throw IllegalArgumentException(); + + sal_uInt32 nSize = aSequence.getLength(); + if( nSize > 0 ) + { + SvMemoryStream aStream (aSequence.getArray(), nSize, + StreamMode::READ ); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + auto pItemSet = std::make_unique<SfxItemSetFixed< + SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, + SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, + SID_HTML_MODE, SID_HTML_MODE, + FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER>>( mpDoc->GetAttrPool() ); + VclPtr<SfxPrinter> pPrinter = SfxPrinter::Create ( aStream, std::move(pItemSet) ); + assert (! pPrinter->isDisposed() ); + // set printer only once; in _postSetValues + mpPrinter.disposeAndClear(); + mpPrinter = pPrinter; + } + + } + break; + case HANDLE_PRINTER_PAPER: + { + bool bPreferPrinterPapersize = {}; // spurious -Werror=maybe-uninitialized + if(!(rValue >>= bPreferPrinterPapersize)) + throw IllegalArgumentException(); + mbPreferPrinterPapersize = bPreferPrinterPapersize; + } + break; + case HANDLE_IS_KERN_ASIAN_PUNCTUATION: + { + bool bIsKern = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION, bIsKern); + if (SwEditShell* pEditSh = mpDoc->GetEditShell()) + pEditSh->ChgHyphenation(); + } + break; + case HANDLE_CHARACTER_COMPRESSION_TYPE: + { + sal_Int16 nMode = 0; + rValue >>= nMode; + switch (static_cast<CharCompressType>(nMode)) + { + case CharCompressType::NONE: + case CharCompressType::PunctuationOnly: + case CharCompressType::PunctuationAndKana: + break; + default: + throw IllegalArgumentException(); + } + mpDoc->getIDocumentSettingAccess().setCharacterCompressionType(static_cast<CharCompressType>(nMode)); + } + break; + case HANDLE_APPLY_USER_DATA: + { + mpDocSh->SetUseUserData(*o3tl::doAccess<bool>(rValue)); + } + break; + case HANDLE_SAVE_THUMBNAIL: + { + mpDocSh->SetUseThumbnailSave(*o3tl::doAccess<bool>(rValue)); + } + break; + case HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS: + { + bool bSaveGlobal = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, bSaveGlobal ); + } + break; + case HANDLE_CURRENT_DATABASE_DATA_SOURCE: + { + SwDBData aData = mpDoc->GetDBData(); + if ( rValue >>= aData.sDataSource ) + mpDoc->ChgDBData( aData ); + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND: + { + SwDBData aData = mpDoc->GetDBData(); + + if ( rValue >>= aData.sCommand ) + mpDoc->ChgDBData( aData ); + + SAL_WARN_IF( aData.sDataSource.isEmpty() && !aData.sCommand.isEmpty(), "sw.uno", + "\"CurrentDatabaseCommand\" property possibly set before \"CurrentDatabaseDataSource\"" ); + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND_TYPE: + { + SwDBData aData = mpDoc->GetDBData(); + if ( rValue >>= aData.nCommandType ) + mpDoc->ChgDBData( aData ); + SAL_WARN_IF( aData.nCommandType && aData.sDataSource.isEmpty(), "sw.uno", + "\"CurrentDatabaseCommandType\" property possibly set before \"CurrentDatabaseDataSource\"" ); + SAL_WARN_IF( aData.nCommandType && aData.sCommand.isEmpty(), "sw.uno", + "\"CurrentDatabaseCommandType\" property possibly set before \"CurrentDatabaseCommand\"" ); + } + break; + case HANDLE_EMBEDDED_DATABASE_NAME: + { +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + OUString sEmbeddedName; + if (rValue >>= sEmbeddedName) + mpDoc->GetDBManager()->setEmbeddedName(sEmbeddedName, *mpDocSh); +#endif + } + break; + case HANDLE_SAVE_VERSION_ON_CLOSE: + { + mpDocSh->SetSaveVersionOnClose( *o3tl::doAccess<bool>(rValue) ); + } + break; + case HANDLE_UPDATE_FROM_TEMPLATE: + { + mpDocSh->SetQueryLoadTemplate( *o3tl::doAccess<bool>(rValue) ); + } + break; + case HANDLE_PRINTER_INDEPENDENT_LAYOUT: + { + sal_Int16 nTmp = 0; + rValue >>= nTmp; + + bool bUseVirDev = true; + bool bHiResVirDev = true; + if( nTmp == document::PrinterIndependentLayout::DISABLED ) + bUseVirDev = false; + else if ( nTmp == document::PrinterIndependentLayout::LOW_RESOLUTION ) + bHiResVirDev = false; + else if ( nTmp != document::PrinterIndependentLayout::HIGH_RESOLUTION ) + throw IllegalArgumentException(); + + mpDoc->getIDocumentDeviceAccess().setReferenceDeviceType( bUseVirDev, bHiResVirDev ); + } + break; + case HANDLE_IS_LABEL_DOC : + { + bool bSet = false; + if(!(rValue >>= bSet)) + throw IllegalArgumentException(); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::LABEL_DOCUMENT, bSet); + } + break; + case HANDLE_IS_ADD_FLY_OFFSET: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_FLY_OFFSETS, bTmp); + } + break; + case HANDLE_IS_ADD_VERTICAL_FLY_OFFSET: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS, bTmp); + } + break; + case HANDLE_IS_ADD_EXTERNAL_LEADING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_EXT_LEADING, bTmp); + } + break; + case HANDLE_OLD_NUMBERING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::OLD_NUMBERING, bTmp); + } + break; + case HANDLE_OUTLINELEVEL_YIELDS_NUMBERING: + { + // ignore - this is a dead property + } + break; + case HANDLE_ALLOW_PRINTJOB_CANCEL: + { + bool bState = false; + if (!(rValue >>= bState)) + throw IllegalArgumentException(); + mpDocSh->Stamp_SetPrintCancelState(bState); + } + break; + case HANDLE_USE_FORMER_LINE_SPACING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::OLD_LINE_SPACING, bTmp); + } + break; + case HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS, bTmp); + } + break; + case HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, bTmp); + } + break; + case HANDLE_USE_FORMER_OBJECT_POSITIONING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_OBJECT_POS, bTmp); + } + break; + case HANDLE_USE_FORMER_TEXT_WRAPPING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING, bTmp); + } + break; + case HANDLE_CHANGES_PASSWORD: + { + Sequence <sal_Int8> aNew; + if(rValue >>= aNew) + { + mpDoc->getIDocumentRedlineAccess().SetRedlinePassword(aNew); + if(aNew.hasElements()) + { + RedlineFlags eMode = mpDoc->getIDocumentRedlineAccess().GetRedlineFlags(); + eMode |= RedlineFlags::On; + mpDoc->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); + } + } + } + break; + case HANDLE_CONSIDER_WRAP_ON_OBJPOS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION, bTmp ); + } + break; + case HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, bTmp); + } + break; + case HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, bTmp); + } + break; + case HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, bTmp); + } + break; + case HANDLE_TABLE_ROW_KEEP: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TABLE_ROW_KEEP, bTmp); + } + break; + case HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, bTmp); + } + break; + case HANDLE_LOAD_READONLY: + { + mpDocSh->SetLoadReadonly( *o3tl::doAccess<bool>(rValue) ); + } + break; + case HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, bTmp); + } + break; + case HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME, bTmp); + } + break; + case HANDLE_UNIX_FORCE_ZERO_EXT_LEADING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING, bTmp); + } + break; + case HANDLE_USE_OLD_PRINTER_METRICS: + // ignore - this is a dead property + break; + case HANDLE_TABS_RELATIVE_TO_INDENT: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TABS_RELATIVE_TO_INDENT, bTmp); + } + break; + case HANDLE_RSID: + { + sal_uInt32 nTmp = 0; + rValue >>= nTmp; + mpDoc->setRsid( nTmp ); + } + break; + case HANDLE_RSID_ROOT: + { + sal_uInt32 nTmp = 0; + rValue >>= nTmp; + mpDoc->setRsidRoot( nTmp ); + } + break; + case HANDLE_PROTECT_FORM: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FORM, bTmp); + } + break; + case HANDLE_MS_WORD_COMP_TRAILING_BLANKS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, bTmp); + } + break; + case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY, bTmp); + } + break; + case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST, bTmp); + } + break; + case HANDLE_MODIFYPASSWORDINFO: + { + uno::Sequence< beans::PropertyValue > aInfo; + if ( !( rValue >>= aInfo ) ) + throw lang::IllegalArgumentException( + "Value of type Sequence<PropertyValue> expected!", + uno::Reference< uno::XInterface >(), + 2 ); + + if ( !mpDocSh->SetModifyPasswordInfo( aInfo ) ) + throw beans::PropertyVetoException( + "The hash is not allowed to be changed now!", + uno::Reference< uno::XInterface >() ); + } + break; + case HANDLE_MATH_BASELINE_ALIGNMENT: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set( DocumentSettingId::MATH_BASELINE_ALIGNMENT, bTmp ); + } + break; + case HANDLE_INVERT_BORDER_SPACING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::INVERT_BORDER_SPACING, bTmp); + } + break; + case HANDLE_COLLAPSE_EMPTY_CELL_PARA: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA, bTmp); + } + break; + case HANDLE_SMALL_CAPS_PERCENTAGE_66: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SMALL_CAPS_PERCENTAGE_66, bTmp); + } + break; + case HANDLE_TAB_OVERFLOW: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVERFLOW, bTmp); + } + break; + case HANDLE_UNBREAKABLE_NUMBERINGS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::UNBREAKABLE_NUMBERINGS, bTmp); + } + break; + case HANDLE_STYLES_NODEFAULT: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::STYLES_NODEFAULT, bTmp); + } + break; + case HANDLE_CLIPPED_PICTURES: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CLIPPED_PICTURES, bTmp); + } + break; + case HANDLE_BACKGROUND_PARA_OVER_DRAWINGS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS, bTmp); + } + break; + case HANDLE_EMBED_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_FONTS, bTmp); + } + break; + case HANDLE_EMBED_USED_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_USED_FONTS, bTmp); + } + break; + case HANDLE_EMBED_LATIN_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_LATIN_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_ASIAN_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_ASIAN_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_COMPLEX_SCRIPT_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_COMPLEX_SCRIPT_FONTS, bTmp); + } + break; + case HANDLE_EMBED_SYSTEM_FONTS: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMBED_SYSTEM_FONTS, bTmp); + } + break; + case HANDLE_TAB_OVER_MARGIN: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_MARGIN, bTmp); + } + break; + case HANDLE_TAB_OVER_SPACING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_SPACING, bTmp); + } + break; + case HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK, bTmp); + } + break; + case HANDLE_SURROUND_TEXT_WRAP_SMALL: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::SURROUND_TEXT_WRAP_SMALL, bTmp); + } + break; + case HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING: + { + bool bTmp = *o3tl::doAccess<bool>(rValue); + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING, bTmp); + } + break; + case HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE, bTmp); + } + } + break; + case HANDLE_SUBTRACT_FLYS: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::SUBTRACT_FLYS, bTmp); + } + } + break; + case HANDLE_DISABLE_OFF_PAGE_POSITIONING: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING, bTmp); + } + } + break; + case HANDLE_EMPTY_DB_FIELD_HIDES_PARA: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA, + bTmp); + } + } + break; + case HANDLE_CONTINUOUS_ENDNOTES: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::CONTINUOUS_ENDNOTES, + bTmp); + } + } + break; + case HANDLE_PROTECT_BOOKMARKS: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_BOOKMARKS, + bTmp); + } + } + break; + case HANDLE_PROTECT_FIELDS: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FIELDS, + bTmp); + } + } + break; + case HANDLE_HEADER_SPACING_BELOW_LAST_PARA: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::HEADER_SPACING_BELOW_LAST_PARA, bTmp); + } + } + break; + case HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::FRAME_AUTOWIDTH_WITH_MORE_PARA, bTmp); + } + } + break; + case HANDLE_GUTTER_AT_TOP: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set(DocumentSettingId::GUTTER_AT_TOP, bTmp); + } + } + break; + case HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND, bTmp); + } + } + break; + case HANDLE_IMAGE_PREFERRED_DPI: + { + sal_uInt32 nValue = 0; + if (rValue >>= nValue) + { + mpDoc->getIDocumentSettingAccess().setImagePreferredDPI(nValue); + } + } + break; + case HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, bTmp); + } + } + break; + case HANDLE_HYPHENATE_URLS: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::HYPHENATE_URLS, bTmp); + } + } + break; + case HANDLE_DO_NOT_BREAK_WRAPPED_TABLES: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES, bTmp); + } + } + break; + case HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, bTmp); + } + } + break; + case HANDLE_JUSTIFY_LINES_WITH_SHRINKING: + { + bool bTmp; + if (rValue >>= bTmp) + { + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING, bTmp); + } + } + break; + case HANDLE_NO_NUMBERING_SHOW_FOLLOWBY: + { + bool bTmp; + if (rValue >>= bTmp) + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY, bTmp); + } + break; + case HANDLE_DROP_CAP_PUNCTUATION: + { + bool bTmp; + if (rValue >>= bTmp) + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::DROP_CAP_PUNCTUATION, bTmp); + } + break; + case HANDLE_USE_VARIABLE_WIDTH_NBSP: + { + bool bTmp; + if (rValue >>= bTmp) + mpDoc->getIDocumentSettingAccess().set( + DocumentSettingId::USE_VARIABLE_WIDTH_NBSP, bTmp); + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXDocumentSettings::_postSetValues () +{ + // set printer only once, namely here! + if( mpPrinter != nullptr ) + { + // #i86352# the printer is also used as container for options by sfx + // when setting a printer it should have decent default options + SfxItemSet aOptions( mpPrinter->GetOptions() ); + SwPrintData aPrtData( mpDoc->getIDocumentDeviceAccess().getPrintData() ); + SwAddPrinterItem aAddPrinterItem (aPrtData); + aOptions.Put(aAddPrinterItem); + mpPrinter->SetOptions( aOptions ); + mpPrinter->SetPrinterSettingsPreferred( mbPreferPrinterPapersize ); + + mpDoc->getIDocumentDeviceAccess().setPrinter( mpPrinter, true, true ); + } + + mpPrinter = nullptr; + mpDocSh = nullptr; + mpDoc = nullptr; +} + +void SwXDocumentSettings::_preGetValues () +{ + mpDocSh = mpModel->GetDocShell(); + if (nullptr == mpDocSh) + throw UnknownPropertyException(); + mpDoc = mpDocSh->GetDoc(); + if (nullptr == mpDoc) + throw UnknownPropertyException(); +} + +void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue ) +{ + switch( rInfo.mnHandle ) + { + case HANDLE_FORBIDDEN_CHARS: + { + rValue <<= Reference<XForbiddenCharacters>(mpModel->GetPropertyHelper()); + } + break; + case HANDLE_LINK_UPDATE_MODE: + { + rValue <<= static_cast < sal_Int16 > ( mpDoc->getIDocumentSettingAccess().getLinkUpdateMode(true) ); + } + break; + case HANDLE_FIELD_AUTO_UPDATE: + { + SwFieldUpdateFlags nFlags = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true); + rValue <<= nFlags == AUTOUPD_FIELD_ONLY || nFlags == AUTOUPD_FIELD_AND_CHARTS; + } + break; + case HANDLE_CHART_AUTO_UPDATE: + { + SwFieldUpdateFlags nFlags = mpDoc->getIDocumentSettingAccess().getFieldUpdateFlags(true); + rValue <<= nFlags == AUTOUPD_FIELD_AND_CHARTS; + } + break; + case HANDLE_ADD_PARA_TABLE_SPACING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PARA_SPACE_MAX); + } + break; + case HANDLE_ADD_PARA_TABLE_SPACING_AT_START: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES); + } + break; + case HANDLE_ALIGN_TAB_STOP_POSITION: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT); + } + break; + case HANDLE_PRINTER_NAME: + { + SfxPrinter *pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false ); + rValue <<= pPrinter ? pPrinter->GetName() : OUString(); + } + break; + case HANDLE_PRINTER_SETUP: + { + SfxPrinter *pPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false ); + if (pPrinter) + { + SvMemoryStream aStream; + pPrinter->Store( aStream ); + sal_uInt32 nSize = aStream.TellEnd(); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + Sequence < sal_Int8 > aSequence( nSize ); + aStream.ReadBytes(aSequence.getArray(), nSize); + rValue <<= aSequence; + } + else + { + Sequence < sal_Int8 > aSequence ( 0 ); + rValue <<= aSequence; + } + } + break; + case HANDLE_PRINTER_PAPER: + { + SfxPrinter *pTempPrinter = mpDoc->getIDocumentDeviceAccess().getPrinter( false ); + rValue <<= pTempPrinter && pTempPrinter->GetPrinterSettingsPreferred(); + } + break; + case HANDLE_IS_KERN_ASIAN_PUNCTUATION: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::KERN_ASIAN_PUNCTUATION); + } + break; + case HANDLE_APPLY_USER_DATA: + { + rValue <<= mpDocSh->IsUseUserData(); + } + break; + case HANDLE_SAVE_THUMBNAIL: + { + rValue <<= mpDocSh->IsUseThumbnailSave(); + } + break; + case HANDLE_CHARACTER_COMPRESSION_TYPE: + { + rValue <<= static_cast < sal_Int16 > (mpDoc->getIDocumentSettingAccess().getCharacterCompressionType()); + } + break; + case HANDLE_SAVE_GLOBAL_DOCUMENT_LINKS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS); + } + break; + case HANDLE_CURRENT_DATABASE_DATA_SOURCE: + { + const SwDBData& rData = mpDoc->GetDBData(); + rValue <<= rData.sDataSource; + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND: + { + const SwDBData& rData = mpDoc->GetDBData(); + rValue <<= rData.sCommand; + } + break; + case HANDLE_CURRENT_DATABASE_COMMAND_TYPE: + { + const SwDBData& rData = mpDoc->GetDBData(); + rValue <<= rData.nCommandType; + } + break; + case HANDLE_EMBEDDED_DATABASE_NAME: + { +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + rValue <<= mpDoc->GetDBManager()->getEmbeddedName(); +#else + rValue = uno::Any(); +#endif + } + break; + case HANDLE_SAVE_VERSION_ON_CLOSE: + { + rValue <<= mpDocSh->IsSaveVersionOnClose(); + } + break; + case HANDLE_UPDATE_FROM_TEMPLATE: + { + rValue <<= mpDocSh->IsQueryLoadTemplate(); + } + break; + case HANDLE_PRINTER_INDEPENDENT_LAYOUT: + { + // returns short (see css.document.PrinterIndependentLayout) + sal_Int16 nVirDevType = mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_VIRTUAL_DEVICE) ? + ( mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE) ? + document::PrinterIndependentLayout::HIGH_RESOLUTION : + document::PrinterIndependentLayout::LOW_RESOLUTION ) : + document::PrinterIndependentLayout::DISABLED; + rValue <<= nVirDevType; + } + break; + case HANDLE_IS_LABEL_DOC: + { + bool bLabel = mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::LABEL_DOCUMENT); + rValue <<= bLabel; + } + break; + case HANDLE_IS_ADD_FLY_OFFSET: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_FLY_OFFSETS); + } + break; + case HANDLE_IS_ADD_VERTICAL_FLY_OFFSET: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS); + } + break; + case HANDLE_IS_ADD_EXTERNAL_LEADING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_EXT_LEADING); + } + break; + case HANDLE_OLD_NUMBERING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::OLD_NUMBERING); + } + break; + case HANDLE_OUTLINELEVEL_YIELDS_NUMBERING: + { + rValue <<= false; + } + break; + case HANDLE_ALLOW_PRINTJOB_CANCEL: + { + rValue <<= mpDocSh->Stamp_GetPrintCancelState(); + } + break; + case HANDLE_USE_FORMER_LINE_SPACING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING); + } + break; + case HANDLE_ADD_PARA_SPACING_TO_TABLE_CELLS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS); + } + break; + case HANDLE_ADD_PARA_LINE_SPACING_TO_TABLE_CELLS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS); + } + break; + case HANDLE_USE_FORMER_OBJECT_POSITIONING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_OBJECT_POS); + } + break; + case HANDLE_USE_FORMER_TEXT_WRAPPING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING); + } + break; + case HANDLE_CHANGES_PASSWORD: + { + rValue <<= mpDoc->getIDocumentRedlineAccess().GetRedlinePassword(); + } + break; + case HANDLE_CONSIDER_WRAP_ON_OBJPOS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION); + } + break; + case HANDLE_IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING); + } + break; + case HANDLE_DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); + } + break; + case HANDLE_DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT); + } + break; + case HANDLE_TABLE_ROW_KEEP : + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TABLE_ROW_KEEP); + } + break; + case HANDLE_IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION); + } + break; + case HANDLE_LOAD_READONLY: + { + rValue <<= mpDocSh->IsLoadReadonly(); + } + break; + case HANDLE_DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE); + } + break; + case HANDLE_CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAMES: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME); + } + break; + case HANDLE_UNIX_FORCE_ZERO_EXT_LEADING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::UNIX_FORCE_ZERO_EXT_LEADING); + } + break; + case HANDLE_USE_OLD_PRINTER_METRICS: + { + rValue <<= false; + } + break; + case HANDLE_TABS_RELATIVE_TO_INDENT: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT); + } + break; + case HANDLE_RSID: + { + rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsid() ); + } + break; + case HANDLE_RSID_ROOT: + { + rValue <<= static_cast < sal_Int32 > ( mpDoc->getRsidRoot() ); + } + break; + case HANDLE_PROTECT_FORM: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_FORM); + } + break; + case HANDLE_MS_WORD_COMP_TRAILING_BLANKS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS); + } + break; + case HANDLE_MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY); + } + break; + case HANDLE_TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST); + } + break; + case HANDLE_MODIFYPASSWORDINFO: + { + rValue <<= mpDocSh->GetModifyPasswordInfo(); + } + break; + case HANDLE_MATH_BASELINE_ALIGNMENT: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ); + } + break; + case HANDLE_INVERT_BORDER_SPACING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::INVERT_BORDER_SPACING); + } + break; + case HANDLE_COLLAPSE_EMPTY_CELL_PARA: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA ); + } + break; + case HANDLE_SMALL_CAPS_PERCENTAGE_66: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::SMALL_CAPS_PERCENTAGE_66 ); + } + break; + case HANDLE_TAB_OVERFLOW: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TAB_OVERFLOW ); + } + break; + case HANDLE_UNBREAKABLE_NUMBERINGS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::UNBREAKABLE_NUMBERINGS ); + } + break; + case HANDLE_STYLES_NODEFAULT: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::STYLES_NODEFAULT ); + } + break; + case HANDLE_CLIPPED_PICTURES: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::CLIPPED_PICTURES ); + } + break; + case HANDLE_BACKGROUND_PARA_OVER_DRAWINGS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::BACKGROUND_PARA_OVER_DRAWINGS ); + } + break; + case HANDLE_EMBED_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_FONTS ); + } + break; + case HANDLE_EMBED_USED_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_USED_FONTS ); + } + break; + case HANDLE_EMBED_LATIN_SCRIPT_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_LATIN_SCRIPT_FONTS ); + } + break; + case HANDLE_EMBED_ASIAN_SCRIPT_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_ASIAN_SCRIPT_FONTS ); + } + break; + case HANDLE_EMBED_COMPLEX_SCRIPT_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_COMPLEX_SCRIPT_FONTS ); + } + break; + case HANDLE_EMBED_SYSTEM_FONTS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::EMBED_SYSTEM_FONTS ); + } + break; + case HANDLE_TAB_OVER_MARGIN: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TAB_OVER_MARGIN ); + } + break; + case HANDLE_TAB_OVER_SPACING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_SPACING); + } + break; + case HANDLE_TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK ); + } + break; + case HANDLE_SURROUND_TEXT_WRAP_SMALL: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::SURROUND_TEXT_WRAP_SMALL ); + } + break; + case HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ); + } + break; + case HANDLE_PROP_LINE_SPACING_SHRINKS_FIRST_LINE: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE); + } + break; + case HANDLE_SUBTRACT_FLYS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::SUBTRACT_FLYS); + } + break; + case HANDLE_DISABLE_OFF_PAGE_POSITIONING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING); + } + break; + case HANDLE_EMPTY_DB_FIELD_HIDES_PARA: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA); + } + break; + case HANDLE_CONTINUOUS_ENDNOTES: + { + rValue + <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::CONTINUOUS_ENDNOTES); + } + break; + case HANDLE_PROTECT_BOOKMARKS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::PROTECT_BOOKMARKS); + } + break; + case HANDLE_PROTECT_FIELDS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::PROTECT_FIELDS); + } + break; + case HANDLE_HEADER_SPACING_BELOW_LAST_PARA: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::HEADER_SPACING_BELOW_LAST_PARA); + } + break; + case HANDLE_FRAME_AUTOWIDTH_WITH_MORE_PARA: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::FRAME_AUTOWIDTH_WITH_MORE_PARA); + } + break; + case HANDLE_GUTTER_AT_TOP: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP); + } + break; + case HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND); + } + break; + case HANDLE_IMAGE_PREFERRED_DPI: + { + rValue <<= mpDoc->getIDocumentSettingAccess().getImagePreferredDPI(); + } + break; + case HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE); + } + break; + case HANDLE_HYPHENATE_URLS: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::HYPHENATE_URLS); + } + break; + case HANDLE_DO_NOT_BREAK_WRAPPED_TABLES: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES); + } + break; + case HANDLE_ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK); + } + break; + case HANDLE_JUSTIFY_LINES_WITH_SHRINKING: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING); + } + break; + case HANDLE_NO_NUMBERING_SHOW_FOLLOWBY: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY); + } + break; + case HANDLE_DROP_CAP_PUNCTUATION: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::DROP_CAP_PUNCTUATION); + } + break; + case HANDLE_USE_VARIABLE_WIDTH_NBSP: + { + rValue <<= mpDoc->getIDocumentSettingAccess().get( + DocumentSettingId::USE_VARIABLE_WIDTH_NBSP); + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXDocumentSettings::_postGetValues () +{ + mpDocSh = nullptr; + mpDoc = nullptr; +} + +// XServiceInfo +OUString SAL_CALL SwXDocumentSettings::getImplementationName( ) +{ + return "SwXDocumentSettings"; +} + +sal_Bool SAL_CALL SwXDocumentSettings::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString > SAL_CALL SwXDocumentSettings::getSupportedServiceNames( ) +{ + return { "com.sun.star.document.Settings", "com.sun.star.text.DocumentSettings", "com.sun.star.text.PrintSettings" }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/SwXDocumentSettings.hxx b/sw/source/uibase/uno/SwXDocumentSettings.hxx new file mode 100644 index 0000000000..3d722e40ba --- /dev/null +++ b/sw/source/uibase/uno/SwXDocumentSettings.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <comphelper/MasterPropertySet.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <cppuhelper/weak.hxx> +#include <vcl/vclptr.hxx> + +class SwXTextDocument; +class SwDocShell; +class SwDoc; +class SfxPrinter; + +class SwXDocumentSettings final : + public comphelper::MasterPropertySet, + public css::lang::XServiceInfo, + public css::lang::XTypeProvider, + public cppu::OWeakObject +{ + SwXTextDocument* mpModel; + SwDocShell* mpDocSh; + SwDoc* mpDoc; + + /** the printer should be set only once; since there are several + * printer-related properties, remember the last printer and set it in + * _postSetValues */ + VclPtr<SfxPrinter> mpPrinter; + bool mbPreferPrinterPapersize; + + virtual void _preSetValues () override; + virtual void _setSingleValue( const comphelper::PropertyInfo & rInfo, const css::uno::Any &rValue ) override; + virtual void _postSetValues () override; + + virtual void _preGetValues () override; + virtual void _getSingleValue( const comphelper::PropertyInfo & rInfo, css::uno::Any & rValue ) override; + virtual void _postGetValues () override; + virtual ~SwXDocumentSettings() + noexcept override; +public: + SwXDocumentSettings( SwXTextDocument* pModel ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire( ) + noexcept override; + virtual void SAL_CALL release( ) + noexcept override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/SwXFilterOptions.cxx b/sw/source/uibase/uno/SwXFilterOptions.cxx new file mode 100644 index 0000000000..f73a4b0dd0 --- /dev/null +++ b/sw/source/uibase/uno/SwXFilterOptions.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <SwXFilterOptions.hxx> +#include <shellio.hxx> +#include <swdll.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotxdoc.hxx> + +#include <swabstdlg.hxx> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::lang; + +constexpr OUString FILTER_OPTIONS_NAME = u"FilterOptions"_ustr; + +SwXFilterOptions::SwXFilterOptions() +{ +} + +SwXFilterOptions::~SwXFilterOptions() +{ +} + +uno::Sequence< beans::PropertyValue > SwXFilterOptions::getPropertyValues() +{ + return comphelper::InitPropertySequence({ + { FILTER_OPTIONS_NAME, uno::Any(m_sFilterOptions) } + }); +} + +void SwXFilterOptions::setPropertyValues( const uno::Sequence<beans::PropertyValue >& aProps ) +{ + for (const beans::PropertyValue& rProp : aProps) + { + OUString aPropName = rProp.Name; + + if ( aPropName == FILTER_OPTIONS_NAME ) + rProp.Value >>= m_sFilterOptions; + else if ( aPropName == "InputStream" ) + rProp.Value >>= m_xInputStream; + } +} + +void SwXFilterOptions::setTitle( const OUString& /*rTitle*/ ) +{ +} + +sal_Int16 SwXFilterOptions::execute() +{ + sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL; + + std::unique_ptr<SvStream> pInStream; + if ( m_xInputStream.is() ) + pInStream = utl::UcbStreamHelper::CreateStream( m_xInputStream ); + + SwDocShell* pDocShell = nullptr; + if (auto pXDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(m_xModel); pXDoc) + pDocShell = pXDoc->GetDocShell(); + + if(pDocShell) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSwAsciiFilterDlg> pAsciiDlg(pFact->CreateSwAsciiFilterDlg(Application::GetFrameWeld(m_xDialogParent), *pDocShell, + pInStream.get())); + if(RET_OK == pAsciiDlg->Execute()) + { + SwAsciiOptions aOptions; + pAsciiDlg->FillOptions( aOptions ); + aOptions.WriteUserData(m_sFilterOptions); + nRet = ui::dialogs::ExecutableDialogResults::OK; + } + } + + return nRet; +} + +void SwXFilterOptions::setTargetDocument( const uno::Reference< XComponent >& xDoc ) +{ + m_xModel = xDoc; +} + +void SwXFilterOptions::setSourceDocument( const uno::Reference<XComponent >& xDoc ) +{ + m_xModel = xDoc; +} + +void SAL_CALL SwXFilterOptions::initialize(const uno::Sequence<uno::Any>& rArguments) +{ + ::comphelper::NamedValueCollection aProperties(rArguments); + if (aProperties.has("ParentWindow")) + aProperties.get("ParentWindow") >>= m_xDialogParent; +} + +OUString SwXFilterOptions::getImplementationName() +{ + return "com.sun.star.comp.Writer.FilterOptionsDialog"; +} + +sal_Bool SwXFilterOptions::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SwXFilterOptions::getSupportedServiceNames() +{ + return { "com.sun.star.ui.dialogs.FilterOptionsDialog" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_Writer_FilterOptionsDialog_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + SolarMutexGuard aGuard; + + //the module may not be loaded + SwGlobals::ensure(); + return cppu::acquire(new SwXFilterOptions()); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/dlelstnr.cxx b/sw/source/uibase/uno/dlelstnr.cxx new file mode 100644 index 0000000000..6cfe6f9719 --- /dev/null +++ b/sw/source/uibase/uno/dlelstnr.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/linguistic2/LinguServiceManager.hpp> +#include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp> +#include <com/sun/star/linguistic2/XProofreadingIterator.hpp> +#include <com/sun/star/linguistic2/LinguServiceEventFlags.hpp> + +#include <unotools/lingucfg.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <comphelper/processfactory.hxx> +#include <vcl/svapp.hxx> +#include <dlelstnr.hxx> +#include <proofreadingiterator.hxx> +#include <swmodule.hxx> +#include <wrtsh.hxx> +#include <view.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::linguistic2; +using namespace ::com::sun::star::linguistic2::LinguServiceEventFlags; + +SwLinguServiceEventListener::SwLinguServiceEventListener() +{ + Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); + try + { + m_xDesktop = frame::Desktop::create(xContext); + m_xDesktop->addTerminateListener( this ); + + m_xLngSvcMgr = LinguServiceManager::create(xContext); + m_xLngSvcMgr->addLinguServiceManagerListener( static_cast<XLinguServiceEventListener *>(this) ); + + if (SvtLinguConfig().HasGrammarChecker()) + { + m_xGCIterator = sw::proofreadingiterator::get(xContext); + Reference< XLinguServiceEventBroadcaster > xBC( m_xGCIterator, UNO_QUERY ); + if (xBC.is()) + xBC->addLinguServiceEventListener( static_cast<XLinguServiceEventListener *>(this) ); + } + } + catch (const uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "sw", "SwLinguServiceEventListener c-tor" ); + } +} + +SwLinguServiceEventListener::~SwLinguServiceEventListener() +{ +} + +void SAL_CALL SwLinguServiceEventListener::processLinguServiceEvent( + const LinguServiceEvent& rLngSvcEvent ) +{ + SolarMutexGuard aGuard; + + bool bIsSpellWrong = 0 != (rLngSvcEvent.nEvent & SPELL_WRONG_WORDS_AGAIN); + bool bIsSpellAll = 0 != (rLngSvcEvent.nEvent & SPELL_CORRECT_WORDS_AGAIN); + if (0 != (rLngSvcEvent.nEvent & PROOFREAD_AGAIN)) + bIsSpellWrong = bIsSpellAll = true; // have all spelling and grammar checked... + if (bIsSpellWrong || bIsSpellAll) + { + SwModule::CheckSpellChanges( false, bIsSpellWrong, bIsSpellAll, false ); + } + if (!(rLngSvcEvent.nEvent & HYPHENATE_AGAIN)) + return; + + SwView *pSwView = SwModule::GetFirstView(); + + //!! since this function may be called within the ctor of + //!! SwView (during formatting) where the WrtShell is not yet + //!! created, we have to check for the WrtShellPtr to see + //!! if it is already available + while (pSwView && pSwView->GetWrtShellPtr()) + { + pSwView->GetWrtShell().ChgHyphenation(); + pSwView = SwModule::GetNextView( pSwView ); + } +} + +void SAL_CALL SwLinguServiceEventListener::disposing( + const EventObject& rEventObj ) +{ + SolarMutexGuard aGuard; + + if (m_xLngSvcMgr.is() && rEventObj.Source == m_xLngSvcMgr) + m_xLngSvcMgr = nullptr; + if (m_xLngSvcMgr.is() && rEventObj.Source == m_xGCIterator) + m_xGCIterator = nullptr; +} + +void SAL_CALL SwLinguServiceEventListener::queryTermination( + const EventObject& /*rEventObj*/ ) +{ +} + +void SAL_CALL SwLinguServiceEventListener::notifyTermination( + const EventObject& rEventObj ) +{ + SolarMutexGuard aGuard; + + if (m_xDesktop.is() && rEventObj.Source == m_xDesktop) + { + if (m_xLngSvcMgr.is()) + m_xLngSvcMgr = nullptr; + if (m_xGCIterator.is()) + m_xGCIterator = nullptr; + m_xDesktop = nullptr; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx new file mode 100644 index 0000000000..4843af4cf4 --- /dev/null +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -0,0 +1,492 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <unotxdoc.hxx> + +#include <map> +#include <utility> +#include <vector> + +#include <com/sun/star/beans/XPropertyAccess.hpp> + +#include <comphelper/sequence.hxx> +#include <o3tl/string_view.hxx> +#include <tools/json_writer.hxx> +#include <tools/urlobj.hxx> +#include <xmloff/odffields.hxx> + +#include <IDocumentMarkAccess.hxx> +#include <doc.hxx> +#include <docsh.hxx> +#include <fmtrfmrk.hxx> +#include <wrtsh.hxx> +#include <txtrfmrk.hxx> +#include <ndtxt.hxx> + +using namespace ::com::sun::star; + +namespace +{ +/// Implements getCommandValues(".uno:TextFormFields"). +/// +/// Parameters: +/// +/// - type: e.g. ODF_UNHANDLED +/// - commandPrefix: field command prefix to not return all fieldmarks +void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aType; + OUString aCommandPrefix; + { + auto it = rArguments.find("type"); + if (it != rArguments.end()) + { + aType = it->second; + } + + it = rArguments.find("commandPrefix"); + if (it != rArguments.end()) + { + aCommandPrefix = it->second; + } + } + + SwDoc* pDoc = pDocShell->GetDoc(); + IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess(); + tools::ScopedJsonWriterArray aFields = rJsonWriter.startArray("fields"); + for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it) + { + auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it); + assert(pFieldmark); + if (pFieldmark->GetFieldname() != aType) + { + continue; + } + + auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); + if (itParam == pFieldmark->GetParameters()->end()) + { + continue; + } + + OUString aCommand; + itParam->second >>= aCommand; + if (!aCommand.startsWith(aCommandPrefix)) + { + continue; + } + + tools::ScopedJsonWriterStruct aField = rJsonWriter.startStruct(); + rJsonWriter.put("type", aType); + rJsonWriter.put("command", aCommand); + } +} + +/// Implements getCommandValues(".uno:TextFormField"). +/// +/// Parameters: +/// +/// - type: e.g. ODF_UNHANDLED +/// - commandPrefix: field command prefix to not return all fieldmarks +void GetTextFormField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aType; + OUString aCommandPrefix; + auto it = rArguments.find("type"); + if (it != rArguments.end()) + { + aType = it->second; + } + + it = rArguments.find("commandPrefix"); + if (it != rArguments.end()) + { + aCommandPrefix = it->second; + } + + IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint(); + sw::mark::IFieldmark* pFieldmark = rIDMA.getInnerFieldmarkFor(rCursor); + auto typeNode = rJsonWriter.startNode("field"); + if (!pFieldmark) + { + return; + } + + if (pFieldmark->GetFieldname() != aType) + { + return; + } + + auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); + if (itParam == pFieldmark->GetParameters()->end()) + { + return; + } + + OUString aCommand; + itParam->second >>= aCommand; + if (!aCommand.startsWith(aCommandPrefix)) + { + return; + } + + rJsonWriter.put("type", aType); + rJsonWriter.put("command", aCommand); +} + +/// Implements getCommandValues(".uno:SetDocumentProperties"). +/// +/// Parameters: +/// +/// - namePrefix: field name prefix to not return all user-defined properties +void GetDocumentProperties(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(), + uno::UNO_QUERY); + uno::Reference<document::XDocumentProperties> xDP = xDPS->getDocumentProperties(); + uno::Reference<beans::XPropertyAccess> xUDP(xDP->getUserDefinedProperties(), uno::UNO_QUERY); + auto aUDPs = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>( + xUDP->getPropertyValues()); + tools::ScopedJsonWriterArray aProperties = rJsonWriter.startArray("userDefinedProperties"); + for (const auto& rUDP : aUDPs) + { + if (!rUDP.Name.startsWith(aNamePrefix)) + { + continue; + } + + if (rUDP.Value.getValueTypeClass() != uno::TypeClass_STRING) + { + continue; + } + + OUString aValue; + rUDP.Value >>= aValue; + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", rUDP.Name); + rJsonWriter.put("type", "string"); + rJsonWriter.put("value", aValue); + } +} + +/// Implements getCommandValues(".uno:Bookmarks"). +/// +/// Parameters: +/// +/// - namePrefix: bookmark name prefix to not return all bookmarks +void GetBookmarks(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess(); + tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("bookmarks"); + for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it) + { + sw::mark::IMark* pMark = *it; + if (!pMark->GetName().startsWith(aNamePrefix)) + { + continue; + } + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", pMark->GetName()); + } +} + +/// Implements getCommandValues(".uno:Bookmark"). +/// +/// Parameters: +/// +/// - namePrefix: bookmark name prefix to not return all bookmarks +void GetBookmark(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint(); + sw::mark::IMark* pBookmark = rIDMA.getOneInnermostBookmarkFor(rCursor); + tools::ScopedJsonWriterNode aBookmark = rJsonWriter.startNode("bookmark"); + if (!pBookmark) + { + return; + } + + if (!pBookmark->GetName().startsWith(aNamePrefix)) + { + return; + } + + rJsonWriter.put("name", pBookmark->GetName()); +} + +/// Implements getCommandValues(".uno:Fields"). +/// +/// Parameters: +/// +/// - typeName: field type condition to not return all fields +/// - namePrefix: field name prefix to not return all fields +void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aTypeName; + { + auto it = rArguments.find("typeName"); + if (it != rArguments.end()) + { + aTypeName = it->second; + } + } + // See SwFieldTypeFromString(). + if (aTypeName != "SetRef") + { + return; + } + + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + SwDoc* pDoc = pDocShell->GetDoc(); + tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("setRefs"); + std::vector<const SwFormatRefMark*> aRefMarks; + for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i) + { + aRefMarks.push_back(pDoc->GetRefMark(i)); + } + // Sort the refmarks based on their start position. + std::sort(aRefMarks.begin(), aRefMarks.end(), + [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) -> bool { + const SwTextRefMark* pTextRefMark1 = pMark1->GetTextRefMark(); + const SwTextRefMark* pTextRefMark2 = pMark2->GetTextRefMark(); + SwPosition aPos1(pTextRefMark1->GetTextNode(), pTextRefMark1->GetStart()); + SwPosition aPos2(pTextRefMark2->GetTextNode(), pTextRefMark2->GetStart()); + return aPos1 < aPos2; + }); + + for (const auto& pRefMark : aRefMarks) + { + if (!pRefMark->GetRefName().startsWith(aNamePrefix)) + { + continue; + } + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", pRefMark->GetRefName()); + } +} + +/// Implements getCommandValues(".uno:Field"). +/// +/// Parameters: +/// +/// - typeName: field type condition to not return all fields +/// - namePrefix: field name prefix to not return all fields +void GetField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aTypeName; + { + auto it = rArguments.find("typeName"); + if (it != rArguments.end()) + { + aTypeName = it->second; + } + } + // See SwFieldTypeFromString(). + if (aTypeName != "SetRef") + { + return; + } + + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint(); + SwTextNode* pTextNode = rCursor.GetNode().GetTextNode(); + std::vector<SwTextAttr*> aAttrs + = pTextNode->GetTextAttrsAt(rCursor.GetContentIndex(), RES_TXTATR_REFMARK); + tools::ScopedJsonWriterNode aRefmark = rJsonWriter.startNode("setRef"); + if (aAttrs.empty()) + { + return; + } + + const SwFormatRefMark& rRefmark = aAttrs[0]->GetRefMark(); + if (!rRefmark.GetRefName().startsWith(aNamePrefix)) + { + return; + } + + rJsonWriter.put("name", rRefmark.GetRefName()); +} + +/// Implements getCommandValues(".uno:Sections"). +/// +/// Parameters: +/// +/// - namePrefix: field name prefix to not return all sections +void GetSections(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + SwDoc* pDoc = pDocShell->GetDoc(); + tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("sections"); + for (const auto& pSection : pDoc->GetSections()) + { + if (!pSection->GetName().startsWith(aNamePrefix)) + { + continue; + } + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", pSection->GetName()); + } +} +} + +bool SwXTextDocument::supportsCommand(std::u16string_view rCommand) +{ + static const std::initializer_list<std::u16string_view> vForward + = { u"TextFormFields", u"TextFormField", u"SetDocumentProperties", + u"Bookmarks", u"Fields", u"Sections", + u"Bookmark", u"Field" }; + + return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end(); +} + +void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) +{ + std::map<OUString, OUString> aMap; + + static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields"); + static constexpr OStringLiteral aTextFormField(".uno:TextFormField"); + static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties"); + static constexpr OStringLiteral aBookmarks(".uno:Bookmarks"); + static constexpr OStringLiteral aFields(".uno:Fields"); + static constexpr OStringLiteral aSections(".uno:Sections"); + static constexpr OStringLiteral aBookmark(".uno:Bookmark"); + static constexpr OStringLiteral aField(".uno:Field"); + + INetURLObject aParser(OUString::fromUtf8(rCommand)); + OUString aArguments = aParser.GetParam(); + sal_Int32 nParamIndex = 0; + do + { + std::u16string_view aParam = o3tl::getToken(aArguments, 0, '&', nParamIndex); + sal_Int32 nIndex = 0; + OUString aKey; + OUString aValue; + do + { + std::u16string_view aToken = o3tl::getToken(aParam, 0, '=', nIndex); + if (aKey.isEmpty()) + aKey = aToken; + else + aValue = aToken; + } while (nIndex >= 0); + OUString aDecodedValue + = INetURLObject::decode(aValue, INetURLObject::DecodeMechanism::WithCharset); + aMap[aKey] = aDecodedValue; + } while (nParamIndex >= 0); + + if (o3tl::starts_with(rCommand, aTextFormFields)) + { + GetTextFormFields(rJsonWriter, m_pDocShell, aMap); + } + if (o3tl::starts_with(rCommand, aTextFormField)) + { + GetTextFormField(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aSetDocumentProperties)) + { + GetDocumentProperties(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aBookmarks)) + { + GetBookmarks(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aFields)) + { + GetFields(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aSections)) + { + GetSections(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aBookmark)) + { + GetBookmark(rJsonWriter, m_pDocShell, aMap); + } + else if (o3tl::starts_with(rCommand, aField)) + { + GetField(rJsonWriter, m_pDocShell, aMap); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unoatxt.cxx b/sw/source/uibase/uno/unoatxt.cxx new file mode 100644 index 0000000000..7ea3d9db4e --- /dev/null +++ b/sw/source/uibase/uno/unoatxt.cxx @@ -0,0 +1,993 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/container/ElementExistException.hpp> +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> +#include <rtl/character.hxx> +#include <utility> +#include <vcl/svapp.hxx> +#include <svtools/unoevent.hxx> +#include <sfx2/event.hxx> +#include <glosdoc.hxx> +#include <shellio.hxx> +#include <initui.hxx> +#include <gloslst.hxx> +#include <unoatxt.hxx> +#include <unomap.hxx> +#include <unotextbodyhf.hxx> +#include <unotextrange.hxx> +#include <TextCursorHelper.hxx> +#include <doc.hxx> +#include <IDocumentContentOperations.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <IDocumentState.hxx> +#include <docsh.hxx> +#include <swdll.hxx> +#include <svl/hint.hxx> +#include <tools/urlobj.hxx> +#include <svl/macitem.hxx> +#include <editeng/acorrcfg.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <memory> + +using namespace ::com::sun::star; + +SwXAutoTextContainer::SwXAutoTextContainer() +{ + m_pGlossaries = ::GetGlossaries(); + +} + +SwXAutoTextContainer::~SwXAutoTextContainer() +{ + +} + +sal_Int32 SwXAutoTextContainer::getCount() +{ + OSL_ENSURE(m_pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32), + "SwXAutoTextContainer::getCount: too many items"); + return static_cast<sal_Int32>(m_pGlossaries->GetGroupCnt()); +} + +uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex) +{ + SolarMutexGuard aGuard; + const size_t nCount = m_pGlossaries->GetGroupCnt(); + if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount ) + throw lang::IndexOutOfBoundsException(); + return getByName(m_pGlossaries->GetGroupName( static_cast<size_t>(nIndex) )); +} + +uno::Type SwXAutoTextContainer::getElementType() +{ + return cppu::UnoType<text::XAutoTextGroup>::get(); + +} + +sal_Bool SwXAutoTextContainer::hasElements() +{ + // At least standard should always exists! + return true; +} + +uno::Any SwXAutoTextContainer::getByName(const OUString& GroupName) +{ + SolarMutexGuard aGuard; + + uno::Reference< text::XAutoTextGroup > xGroup; + if ( m_pGlossaries && hasByName( GroupName ) ) // group name already known? + // true = create group if not already available + xGroup = m_pGlossaries->GetAutoTextGroup( GroupName ); + + if ( !xGroup.is() ) + throw container::NoSuchElementException(); + + return css::uno::Any( xGroup ); +} + +uno::Sequence< OUString > SwXAutoTextContainer::getElementNames() +{ + SolarMutexGuard aGuard; + const size_t nCount = m_pGlossaries->GetGroupCnt(); + OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32), + "SwXAutoTextContainer::getElementNames: too many groups"); + + uno::Sequence< OUString > aGroupNames(static_cast<sal_Int32>(nCount)); + OUString *pArr = aGroupNames.getArray(); + + for ( size_t i = 0; i < nCount; ++i ) + { + // The names will be passed without a path extension. + pArr[i] = m_pGlossaries->GetGroupName(i).getToken(0, GLOS_DELIM); + } + return aGroupNames; +} +// Finds group names with or without path index. +sal_Bool SwXAutoTextContainer::hasByName(const OUString& Name) +{ + SolarMutexGuard aGuard; + OUString sGroupName( m_pGlossaries->GetCompleteGroupName( Name ) ); + if(!sGroupName.isEmpty()) + return true; + return false; +} + +uno::Reference< text::XAutoTextGroup > SwXAutoTextContainer::insertNewByName( + const OUString& aGroupName) +{ + SolarMutexGuard aGuard; + if(hasByName(aGroupName)) + throw container::ElementExistException(); + //check for non-ASCII characters + if(aGroupName.isEmpty()) + { + throw lang::IllegalArgumentException("group name must not be empty", nullptr, 0); + } + for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++) + { + sal_Unicode cChar = aGroupName[nPos]; + if (rtl::isAsciiAlphanumeric(cChar) || + (cChar == '_') || + (cChar == 0x20) || + (cChar == GLOS_DELIM) ) + { + continue; + } + throw lang::IllegalArgumentException("group name must contain a-z, A-z, '_', ' ' only", nullptr, 0); + } + OUString sGroup(aGroupName); + if (sGroup.indexOf(GLOS_DELIM)<0) + { + sGroup += OUStringChar(GLOS_DELIM) + "0"; + } + m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM)); + + uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup ); + OSL_ENSURE( xGroup.is(), "SwXAutoTextContainer::insertNewByName: no UNO object created? How this?" ); + // We just inserted the group into the glossaries, so why doesn't it exist? + + return xGroup; +} + +void SwXAutoTextContainer::removeByName(const OUString& aGroupName) +{ + SolarMutexGuard aGuard; + // At first find the name with path extension + OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName ); + if(sGroupName.isEmpty()) + throw container::NoSuchElementException(); + m_pGlossaries->DelGroupDoc(sGroupName); +} + +OUString SwXAutoTextContainer::getImplementationName() +{ + return "SwXAutoTextContainer"; +} + +sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames() +{ + return { "com.sun.star.text.AutoTextContainer" }; +} + +SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName, + SwGlossaries* pGlos) : + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)), + m_pGlossaries(pGlos), + m_sName(rName), + m_sGroupName(rName) +{ + OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ), + "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" ); +} + +SwXAutoTextGroup::~SwXAutoTextGroup() +{ +} + +uno::Sequence< OUString > SwXAutoTextGroup::getTitles() +{ + SolarMutexGuard aGuard; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + const sal_uInt16 nCount = pGlosGroup->GetCount(); + + uno::Sequence< OUString > aEntryTitles(nCount); + OUString *pArr = aEntryTitles.getArray(); + + for ( sal_uInt16 i = 0; i < nCount; i++ ) + pArr[i] = pGlosGroup->GetLongName(i); + return aEntryTitles; +} + +void SwXAutoTextGroup::renameByName(const OUString& aElementName, + const OUString& aNewElementName, const OUString& aNewElementTitle) +{ + SolarMutexGuard aGuard; + // throw exception only if the programmatic name is to be changed into an existing name + if(aNewElementName != aElementName && hasByName(aNewElementName)) + throw container::ElementExistException(); + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if(!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + + const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName); + if(USHRT_MAX == nIdx) + throw lang::IllegalArgumentException(); + OUString aNewShort(aNewElementName); + OUString aNewName(aNewElementTitle); + sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort ); + sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName ); + + if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx) + && (nOldIdx == USHRT_MAX || nOldIdx == nIdx)) + { + pGlosGroup->Rename( nIdx, &aNewShort, &aNewName ); + if(pGlosGroup->GetError() != ERRCODE_NONE) + throw io::IOException(); + } + +} + +static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange) +{ + SwNodes& rNds = rInsDoc.GetNodes(); + + SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 ); + SwContentNode * pNd = aIdx.GetNode().GetContentNode(); + SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0); + + bool bRet = false; + rInsDoc.getIDocumentFieldsAccess().LockExpFields(); + { + SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc()); + SwPaM aPam(pDoc->GetNodes()); + SwPaM * pPam(nullptr); + if(pxCursor) + { + pPam = pxCursor->GetPaM(); + } + else + { + if (pxRange->GetPositions(aPam)) + { + pPam = & aPam; + } + } + if (!pPam) { return false; } + bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly) + || bRet; + } + + rInsDoc.getIDocumentFieldsAccess().UnlockExpFields(); + if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() ) + rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true); + + return bRet; +} + +uno::Reference< text::XAutoTextEntry > SwXAutoTextGroup::insertNewByName(const OUString& aName, + const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange) +{ + SolarMutexGuard aGuard; + if(hasByName(aName)) + throw container::ElementExistException(); + if(!xTextRange.is()) + throw uno::RuntimeException(); + + std::unique_ptr<SwTextBlocks> pGlosGroup; + if (m_pGlossaries) + pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName); + const OUString& sShortName(aName); + const OUString& sLongName(aTitle); + if (pGlosGroup && !pGlosGroup->GetError()) + { + SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get()); + OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()); + + OUString sOnlyText; + OUString* pOnlyText = nullptr; + bool bNoAttr = !pxCursor && !pxRange; + if(bNoAttr) + { + sOnlyText = xTextRange->getString(); + pOnlyText = &sOnlyText; + } + + const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get(); + + SwDoc* pGDoc = pGlosGroup->GetDoc(); + + // Until there is an option for that, delete base util::URL + if(rCfg.IsSaveRelFile()) + { + INetURLObject aTemp(pGlosGroup->GetFileName()); + pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + } + else + pGlosGroup->SetBaseURL( OUString() ); + + sal_uInt16 nRet = USHRT_MAX; + if( pOnlyText ) + nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText ); + else + { + pGlosGroup->ClearDoc(); + if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) ) + { + pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines ); + lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange); + pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE); + nRet = pGlosGroup->PutDoc(); + } + } + + if (nRet == USHRT_MAX) + { + throw uno::RuntimeException(); + } + } + pGlosGroup.reset(); + + uno::Reference< text::XAutoTextEntry > xEntry; + + try + { + xEntry = m_pGlossaries ? + m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) : + uno::Reference< text::XAutoTextEntry >(); + OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::insertNewByName: no UNO object created? How this?" ); + // we just inserted the entry into the group, so why doesn't it exist? + } + catch (const container::ElementExistException&) + { + throw; + } + catch (const uno::RuntimeException&) + { + throw; + } + catch (const uno::Exception&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetRuntimeException( + "Error Getting AutoText!", + getXWeak(), + anyEx ); + } + + return xEntry; +} + +void SwXAutoTextGroup::removeByName(const OUString& aEntryName) +{ + SolarMutexGuard aGuard; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if(!pGlosGroup || pGlosGroup->GetError()) + throw container::NoSuchElementException(); + + sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName); + if ( nIdx == USHRT_MAX ) + throw container::NoSuchElementException(); + + pGlosGroup->Delete(nIdx); +} + +OUString SwXAutoTextGroup::getName() +{ + SolarMutexGuard aGuard; + return m_sName; +} + +void SwXAutoTextGroup::setName(const OUString& rName) +{ + SolarMutexGuard aGuard; + if( !m_pGlossaries ) + throw uno::RuntimeException(); + + sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM ); + sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM ); + + OUString aNewSuffix; + if (nNewDelimPos > -1) + aNewSuffix = rName.copy( nNewDelimPos + 1 ); + OUString aOldSuffix; + if (nOldDelimPos > -1) + aOldSuffix = m_sName.copy( nOldDelimPos + 1 ); + + sal_Int32 nNewNumeric = aNewSuffix.toInt32(); + sal_Int32 nOldNumeric = aOldSuffix.toInt32(); + + OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName ); + OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName ); + + if ( m_sName == rName || + ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) ) + return; + OUString sNewGroup(rName); + if (sNewGroup.indexOf(GLOS_DELIM)<0) + { + sNewGroup += OUStringChar(GLOS_DELIM) + "0"; + } + + //the name must be saved, the group may be invalidated while in RenameGroupDoc() + SwGlossaries* pTempGlossaries = m_pGlossaries; + + OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) ); + if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) ) + throw uno::RuntimeException(); + m_sName = rName; + m_sGroupName = sNewGroup; + m_pGlossaries = pTempGlossaries; +} + +sal_Int32 SwXAutoTextGroup::getCount() +{ + SolarMutexGuard aGuard; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + return static_cast<sal_Int32>(pGlosGroup->GetCount()); +} + +uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex) +{ + SolarMutexGuard aGuard; + if (!m_pGlossaries) + throw uno::RuntimeException(); + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName)); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + const sal_uInt16 nCount = pGlosGroup->GetCount(); + if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount) + throw lang::IndexOutOfBoundsException(); + return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex))); +} + +uno::Type SwXAutoTextGroup::getElementType() +{ + return cppu::UnoType<text::XAutoTextEntry>::get(); + +} + +sal_Bool SwXAutoTextGroup::hasElements() +{ + SolarMutexGuard aGuard; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + return pGlosGroup->GetCount() > 0; + +} + +uno::Any SwXAutoTextGroup::getByName(const OUString& _rName) +{ + SolarMutexGuard aGuard; + uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName ); + OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" ); + // we told it to create the object, so why didn't it? + return css::uno::Any( xEntry ); +} + +uno::Sequence< OUString > SwXAutoTextGroup::getElementNames() +{ + SolarMutexGuard aGuard; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + + const sal_uInt16 nCount = pGlosGroup->GetCount(); + uno::Sequence< OUString > aEntryNames(nCount); + OUString *pArr = aEntryNames.getArray(); + + for ( sal_uInt16 i = 0; i < nCount; i++ ) + pArr[i] = pGlosGroup->GetShortName(i); + return aEntryNames; +} + +sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName) +{ + SolarMutexGuard aGuard; + bool bRet = false; + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if (!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + + const sal_uInt16 nCount = pGlosGroup->GetCount(); + for( sal_uInt16 i = 0; i < nCount; ++i ) + { + OUString sCompare(pGlosGroup->GetShortName(i)); + if(sCompare.equalsIgnoreAsciiCase(rName)) + { + bRet = true; + break; + } + } + return bRet; +} + +uno::Reference< beans::XPropertySetInfo > SwXAutoTextGroup::getPropertySetInfo() +{ + static uno::Reference< beans::XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXAutoTextGroup::setPropertyValue( + const OUString& rPropertyName, const uno::Any& aValue) +{ + SolarMutexGuard aGuard; + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + + if(!pEntry) + throw beans::UnknownPropertyException(rPropertyName); + + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if(!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + switch(pEntry->nWID) + { + case WID_GROUP_TITLE: + { + OUString sNewTitle; + aValue >>= sNewTitle; + if(sNewTitle.isEmpty()) + throw lang::IllegalArgumentException(); + bool bChanged = sNewTitle != pGlosGroup->GetName(); + pGlosGroup->SetName(sNewTitle); + if(bChanged && HasGlossaryList()) + GetGlossaryList()->ClearGroups(); + } + break; + } +} + +uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName) +{ + SolarMutexGuard aGuard; + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + + if(!pEntry) + throw beans::UnknownPropertyException(rPropertyName); + std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr); + if(!pGlosGroup || pGlosGroup->GetError()) + throw uno::RuntimeException(); + + uno::Any aAny; + switch(pEntry->nWID) + { + case WID_GROUP_PATH: + aAny <<= pGlosGroup->GetFileName(); + break; + case WID_GROUP_TITLE: + aAny <<= pGlosGroup->GetName(); + break; + } + return aAny; +} + +void SwXAutoTextGroup::addPropertyChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXAutoTextGroup::removePropertyChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXAutoTextGroup::addVetoableChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) +{ +} + +void SwXAutoTextGroup::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/) +{ +} + +void SwXAutoTextGroup::Invalidate() +{ + m_pGlossaries = nullptr; + m_sName.clear(); + m_sGroupName.clear(); +} + +OUString SwXAutoTextGroup::getImplementationName() +{ + return "SwXAutoTextGroup"; +} + +sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames() +{ + uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextGroup" }; + return aRet; +} + +SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName, + OUString aEntryName) : + m_pGlossaries(pGlss), + m_sGroupName(std::move(aGroupName)), + m_sEntryName(std::move(aEntryName)) +{ +} + +SwXAutoTextEntry::~SwXAutoTextEntry() +{ + SolarMutexGuard aGuard; + + // ensure that any pending modifications are written + implFlushDocument( true ); +} + +void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc ) +{ + if ( !m_xDocSh.is() ) + return; + + if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () ) + m_xDocSh->Save(); + + if ( _bCloseDoc ) + { + // stop listening at the document + EndListening( *m_xDocSh ); + + m_xDocSh->DoClose(); + m_xDocSh.clear(); + } +} + +void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint ) +{ + if ( &_rBC != m_xDocSh.get() ) + return; + +// it's our document + if (_rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint) + { + const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(_rHint); + if (SfxEventHintId::PrepareCloseDoc == rEventHint.GetEventId()) + { + implFlushDocument(); + mxBodyText.clear(); + EndListening( *m_xDocSh ); + m_xDocSh.clear(); + } + } + else + { + if ( SfxHintId::Deinitializing == _rHint.GetId() ) + { + // our document is dying (possibly because we're shutting down, and the document was notified + // earlier than we are?) + // stop listening at the docu + EndListening( *m_xDocSh ); + // and release our reference + m_xDocSh.clear(); + } + } +} + +void SwXAutoTextEntry::GetBodyText () +{ + SolarMutexGuard aGuard; + + m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false ); + OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" ); + + // start listening at the document + StartListening( *m_xDocSh ); + + mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() ); +} + +void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&) +{ + SolarMutexGuard g; + implFlushDocument(true); +} + +uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursor() +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + return mxBodyText->createTextCursor(); +} + +uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursorByRange( + const uno::Reference< text::XTextRange > & aTextPosition) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + return mxBodyText->createTextCursorByRange ( aTextPosition ); +} + +void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + mxBodyText->insertString ( xRange, aString, bAbsorb ); +} + +void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb ); +} + +void SwXAutoTextEntry::insertTextContent( + const uno::Reference< text::XTextRange > & xRange, + const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + mxBodyText->insertTextContent ( xRange, xContent, bAbsorb ); +} + +void SwXAutoTextEntry::removeTextContent( + const uno::Reference< text::XTextContent > & xContent) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + mxBodyText->removeTextContent ( xContent ); +} + +uno::Reference< text::XText > SwXAutoTextEntry::getText() +{ + SolarMutexGuard aGuard; + uno::Reference< text::XText > xRet = static_cast<text::XText*>(this); + return xRet; +} + +uno::Reference< text::XTextRange > SwXAutoTextEntry::getStart() +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + return mxBodyText->getStart(); +} + +uno::Reference< text::XTextRange > SwXAutoTextEntry::getEnd() +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + return mxBodyText->getEnd(); +} + +OUString SwXAutoTextEntry::getString() +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + return mxBodyText->getString(); +} + +void SwXAutoTextEntry::setString(const OUString& aString) +{ + SolarMutexGuard aGuard; + EnsureBodyText(); + mxBodyText->setString( aString ); +} + +void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange) +{ + SolarMutexGuard aGuard; + + // ensure that any pending modifications are written + // reason is that we're holding the _copy_ of the auto text, while the real auto text + // is stored somewhere. And below, we're not working with our copy, but only tell the target + // TextRange to work with the stored version. + // #96380# - 2003-03-03 - fs@openoffice.org + implFlushDocument(); + // TODO: think about if we should pass "true" here + // The difference would be that when the next modification is made to this instance here, then + // we would be forced to open the document again, instead of working on our current copy. + // This means that we would reflect any changes which were done to the AutoText by foreign instances + // in the meantime + + // The reference to xKeepAlive is needed during the whole call, likely because it could be a + // different object, not xTextRange itself, and the reference guards it from preliminary death + auto xKeepAlive( xTextRange ); + SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get()); + OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()); + SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get()); + + SwDoc* pDoc = nullptr; + if (pRange) + pDoc = &pRange->GetDoc(); + else if ( pCursor ) + pDoc = pCursor->GetDoc(); + else if ( pText && pText->GetDoc() ) + { + xKeepAlive = pText->getStart(); + pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get()); + if (pCursor) + pDoc = pText->GetDoc(); + } + + if(!pDoc) + throw uno::RuntimeException(); + + SwPaM InsertPaM(pDoc->GetNodes()); + if (pRange) + { + if (!pRange->GetPositions(InsertPaM)) + { + throw uno::RuntimeException(); + } + } + else + { + InsertPaM = *pCursor->GetPaM(); + } + + std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName)); + const bool bResult = pBlock && !pBlock->GetError() + && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM); + + if(!bResult) + throw uno::RuntimeException(); +} + +OUString SwXAutoTextEntry::getImplementationName() +{ + return "SwXAutoTextEntry"; +} + +sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames() +{ + uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextEntry" }; + return aRet; +} + +uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents() +{ + return new SwAutoTextEventDescriptor( *this ); +} + +const struct SvEventDescription aAutotextEvents[] = +{ + { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" }, + { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" }, + { SvMacroItemId::NONE, nullptr } +}; + +SwAutoTextEventDescriptor::SwAutoTextEventDescriptor( + SwXAutoTextEntry& rAutoText ) : + SvBaseEventDescriptor(aAutotextEvents), + m_rAutoTextEntry(rAutoText) +{ +} + +SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor() +{ +} + +OUString SwAutoTextEventDescriptor::getImplementationName() +{ + return "SwAutoTextEventDescriptor"; +} + +void SwAutoTextEventDescriptor::replaceByName( + const SvMacroItemId nEvent, + const SvxMacro& rMacro) +{ + OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), + "Strangely enough, the AutoText vanished!" ); + OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) || + (nEvent == SvMacroItemId::SwStartInsGlossary) , + "Unknown event ID" ); + + SwGlossaries *const pGlossaries = + const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries()); + std::unique_ptr<SwTextBlocks> pBlocks( + pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() )); + OSL_ENSURE( pBlocks, + "can't get autotext group; SwAutoTextEntry has illegal name?"); + + if( !pBlocks || pBlocks->GetError()) + return; + + sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() ); + if( nIndex != USHRT_MAX ) + { + SvxMacroTableDtor aMacroTable; + if( pBlocks->GetMacroTable( nIndex, aMacroTable ) ) + { + aMacroTable.Insert( nEvent, rMacro ); + pBlocks->SetMacroTable( nIndex, aMacroTable ); + } + } + // else: ignore +} + +void SwAutoTextEventDescriptor::getByName( + SvxMacro& rMacro, + const SvMacroItemId nEvent ) +{ + OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" ); + OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) || + (nEvent == SvMacroItemId::SwStartInsGlossary) , + "Unknown event ID" ); + + SwGlossaries *const pGlossaries = + const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries()); + std::unique_ptr<SwTextBlocks> pBlocks( + pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() )); + OSL_ENSURE( pBlocks, + "can't get autotext group; SwAutoTextEntry has illegal name?"); + + // return empty macro, unless macro is found + OUString sEmptyStr; + SvxMacro aEmptyMacro(sEmptyStr, sEmptyStr); + rMacro = aEmptyMacro; + + if ( !pBlocks || pBlocks->GetError()) + return; + + sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() ); + if( nIndex != USHRT_MAX ) + { + SvxMacroTableDtor aMacroTable; + if( pBlocks->GetMacroTable( nIndex, aMacroTable ) ) + { + SvxMacro *pMacro = aMacroTable.Get( nEvent ); + if( pMacro ) + rMacro = *pMacro; + } + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + //the module may not be loaded + SolarMutexGuard aGuard; + SwGlobals::ensure(); + return cppu::acquire(new SwXAutoTextContainer()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unodefaults.cxx b/sw/source/uibase/uno/unodefaults.cxx new file mode 100644 index 0000000000..b12e804108 --- /dev/null +++ b/sw/source/uibase/uno/unodefaults.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "unodefaults.hxx" +#include <svx/unoprov.hxx> +#include <drawdoc.hxx> +#include <doc.hxx> +#include <IDocumentDrawModelAccess.hxx> + +SwSvxUnoDrawPool::SwSvxUnoDrawPool(SwDoc& rDoc) + : SvxUnoDrawPool(rDoc.getIDocumentDrawModelAccess().GetDrawModel(), + SvxPropertySetInfoPool::getWriterDrawingDefaults()) + , m_rDoc(rDoc) +{ +} + +SwSvxUnoDrawPool::~SwSvxUnoDrawPool() noexcept {} + +SfxItemPool* SwSvxUnoDrawPool::getModelPool(bool /*bReadOnly*/) noexcept +{ + // DVO, OD 01.10.2003 #i18732# - return item pool of writer document; + // it contains draw model item pool as secondary pool. + //SdrModel* pModel = m_rDoc.MakeDrawModel(); + //return &pModel->GetItemPool(); + // #i52858# - method name changed + m_rDoc.getIDocumentDrawModelAccess().GetOrCreateDrawModel(); + return &(m_rDoc.GetAttrPool()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unodefaults.hxx b/sw/source/uibase/uno/unodefaults.hxx new file mode 100644 index 0000000000..3e01205950 --- /dev/null +++ b/sw/source/uibase/uno/unodefaults.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <svx/unopool.hxx> + +class SwDoc; + +class SwSvxUnoDrawPool final : public SvxUnoDrawPool +{ + SwDoc& m_rDoc; + +public: + SwSvxUnoDrawPool(SwDoc& rDoc); + virtual ~SwSvxUnoDrawPool() noexcept override; + + virtual SfxItemPool* getModelPool(bool bReadOnly) noexcept override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unodispatch.cxx b/sw/source/uibase/uno/unodispatch.cxx new file mode 100644 index 0000000000..a67afc31c1 --- /dev/null +++ b/sw/source/uibase/uno/unodispatch.cxx @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> + +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <comphelper/servicehelper.hxx> +#include <osl/diagnose.h> +#include <unodispatch.hxx> +#include <view.hxx> +#include <cmdid.h> +#include <wrtsh.hxx> +#include <dbmgr.hxx> + +using namespace ::com::sun::star; + +const char cURLFormLetter[] = ".uno:DataSourceBrowser/FormLetter"; +const char cURLInsertContent[] = ".uno:DataSourceBrowser/InsertContent";//data into fields +const char cURLInsertColumns[] = ".uno:DataSourceBrowser/InsertColumns";//data into text +const char cURLDocumentDataSource[] = ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document +const char cInternalDBChangeNotification[] = ".uno::Writer/DataSourceChanged"; + +SwXDispatchProviderInterceptor::SwXDispatchProviderInterceptor(SwView& rVw) : + m_pView(&rVw) +{ + uno::Reference< frame::XFrame> xUnoFrame = m_pView->GetViewFrame().GetFrame().GetFrameInterface(); + m_xIntercepted.set(xUnoFrame, uno::UNO_QUERY); + if(m_xIntercepted.is()) + { + osl_atomic_increment(&m_refCount); + m_xIntercepted->registerDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this)); + // this should make us the top-level dispatch-provider for the component, via a call to our + // setDispatchProvider we should have got a fallback for requests we (i.e. our master) cannot fulfill + uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this)); + osl_atomic_decrement(&m_refCount); + } +} + +SwXDispatchProviderInterceptor::~SwXDispatchProviderInterceptor() +{ +} + +uno::Reference< frame::XDispatch > SwXDispatchProviderInterceptor::queryDispatch( + const util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags ) +{ + DispatchMutexLock_Impl aLock; + uno::Reference< frame::XDispatch> xResult; + // create some dispatch ... + if(m_pView && aURL.Complete.startsWith(".uno:DataSourceBrowser/")) + { + if(aURL.Complete == cURLFormLetter || + aURL.Complete == cURLInsertContent || + aURL.Complete == cURLInsertColumns || + aURL.Complete == cURLDocumentDataSource) + { + if(!m_xDispatch.is()) + m_xDispatch = new SwXDispatch(*m_pView); + xResult = m_xDispatch; + } + } + + // ask our slave provider + if (!xResult.is() && m_xSlaveDispatcher.is()) + xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags); + + return xResult; +} + +uno::Sequence<OUString> SAL_CALL SwXDispatchProviderInterceptor::getInterceptedURLs() +{ + uno::Sequence<OUString> aRet = + { + OUString(".uno:DataSourceBrowser/*") + }; + + return aRet; +} + +uno::Sequence< uno::Reference< frame::XDispatch > > SwXDispatchProviderInterceptor::queryDispatches( + const uno::Sequence< frame::DispatchDescriptor >& aDescripts ) +{ + DispatchMutexLock_Impl aLock; + uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength()); + std::transform(aDescripts.begin(), aDescripts.end(), aReturn.getArray(), + [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference<frame::XDispatch> { + return queryDispatch(rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags); }); + return aReturn; +} + +uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getSlaveDispatchProvider( ) +{ + DispatchMutexLock_Impl aLock; + return m_xSlaveDispatcher; +} + +void SwXDispatchProviderInterceptor::setSlaveDispatchProvider( + const uno::Reference< frame::XDispatchProvider >& xNewDispatchProvider ) +{ + DispatchMutexLock_Impl aLock; + m_xSlaveDispatcher = xNewDispatchProvider; +} + +uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getMasterDispatchProvider( ) +{ + DispatchMutexLock_Impl aLock; + return m_xMasterDispatcher; +} + +void SwXDispatchProviderInterceptor::setMasterDispatchProvider( + const uno::Reference< frame::XDispatchProvider >& xNewSupplier ) +{ + DispatchMutexLock_Impl aLock; + m_xMasterDispatcher = xNewSupplier; +} + +void SwXDispatchProviderInterceptor::disposing( const lang::EventObject& ) +{ + DispatchMutexLock_Impl aLock; + if (m_xIntercepted.is()) + { + m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this)); + uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this)); + m_xDispatch = nullptr; + } + m_xIntercepted = nullptr; +} + +void SwXDispatchProviderInterceptor::Invalidate() +{ + DispatchMutexLock_Impl aLock; + if (m_xIntercepted.is()) + { + m_xIntercepted->releaseDispatchProviderInterceptor(static_cast<frame::XDispatchProviderInterceptor*>(this)); + uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this)); + m_xDispatch = nullptr; + } + m_xIntercepted = nullptr; + m_pView = nullptr; +} + +SwXDispatch::SwXDispatch(SwView& rVw) : + m_pView(&rVw), + m_bOldEnable(false), + m_bListenerAdded(false) +{ +} + +SwXDispatch::~SwXDispatch() +{ + if(m_bListenerAdded && m_pView) + { + uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject(); + uno::Reference<view::XSelectionChangeListener> xThis = this; + xSupplier->removeSelectionChangeListener(xThis); + } +} + +void SwXDispatch::dispatch(const util::URL& aURL, + const uno::Sequence< beans::PropertyValue >& aArgs) +{ + if(!m_pView) + throw uno::RuntimeException(); +#if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS + (void) aArgs; + if (false) + { + } +#else + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwDBManager* pDBManager = rSh.GetDBManager(); + if(aURL.Complete == cURLInsertContent) + { + svx::ODataAccessDescriptor aDescriptor(aArgs); + SwMergeDescriptor aMergeDesc( DBMGR_MERGE, rSh, aDescriptor ); + pDBManager->Merge(aMergeDesc); + } + else if(aURL.Complete == cURLInsertColumns) + { + SwDBManager::InsertText(rSh, aArgs); + } + else if(aURL.Complete == cURLFormLetter) + { + SfxUnoAnyItem aDBProperties(FN_PARAM_DATABASE_PROPERTIES, uno::Any(aArgs)); + m_pView->GetViewFrame().GetDispatcher()->ExecuteList( + FN_MAILMERGE_WIZARD, + SfxCallMode::ASYNCHRON, + { &aDBProperties }); + } +#endif + else if(aURL.Complete == cURLDocumentDataSource) + { + OSL_FAIL("SwXDispatch::dispatch: this URL is not to be dispatched!"); + } + else if(aURL.Complete == cInternalDBChangeNotification) + { + frame::FeatureStateEvent aEvent; + aEvent.Source = getXWeak(); + + const SwDBData& rData = m_pView->GetWrtShell().GetDBData(); + svx::ODataAccessDescriptor aDescriptor; + aDescriptor.setDataSource(rData.sDataSource); + aDescriptor[svx::DataAccessDescriptorProperty::Command] <<= rData.sCommand; + aDescriptor[svx::DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType; + + aEvent.State <<= aDescriptor.createPropertyValueSequence(); + aEvent.IsEnabled = !rData.sDataSource.isEmpty(); + + // calls to statusChanged may call addStatusListener or removeStatusListener + // so copy m_aStatusListenerVector on stack + auto copyStatusListenerVector = m_aStatusListenerVector; + for (auto & status : copyStatusListenerVector) + { + if(status.aURL.Complete == cURLDocumentDataSource) + { + aEvent.FeatureURL = status.aURL; + status.xListener->statusChanged( aEvent ); + } + } + } + else + throw uno::RuntimeException(); + +} + +void SwXDispatch::addStatusListener( + const uno::Reference< frame::XStatusListener >& xControl, const util::URL& aURL ) +{ + if(!m_pView) + throw uno::RuntimeException(); + ShellMode eMode = m_pView->GetShellMode(); + bool bEnable = ShellMode::Text == eMode || + ShellMode::ListText == eMode || + ShellMode::TableText == eMode || + ShellMode::TableListText == eMode; + + m_bOldEnable = bEnable; + frame::FeatureStateEvent aEvent; + aEvent.IsEnabled = bEnable; + aEvent.Source = getXWeak(); + aEvent.FeatureURL = aURL; + + // one of the URLs requires a special state... + if (aURL.Complete == cURLDocumentDataSource) + { + const SwDBData& rData = m_pView->GetWrtShell().GetDBData(); + + svx::ODataAccessDescriptor aDescriptor; + aDescriptor.setDataSource(rData.sDataSource); + aDescriptor[svx::DataAccessDescriptorProperty::Command] <<= rData.sCommand; + aDescriptor[svx::DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType; + + aEvent.State <<= aDescriptor.createPropertyValueSequence(); + aEvent.IsEnabled = !rData.sDataSource.isEmpty(); + } + + xControl->statusChanged( aEvent ); + + StatusStruct_Impl aStatus; + aStatus.xListener = xControl; + aStatus.aURL = aURL; + m_aStatusListenerVector.emplace_back(aStatus); + + if(!m_bListenerAdded) + { + uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject(); + uno::Reference<view::XSelectionChangeListener> xThis = this; + xSupplier->addSelectionChangeListener(xThis); + m_bListenerAdded = true; + } +} + +void SwXDispatch::removeStatusListener( + const uno::Reference< frame::XStatusListener >& xControl, const util::URL& ) +{ + std::erase_if( + m_aStatusListenerVector, + [&](const StatusStruct_Impl& status) { return status.xListener.get() == xControl.get(); }); + if(m_aStatusListenerVector.empty() && m_pView) + { + uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject(); + uno::Reference<view::XSelectionChangeListener> xThis = this; + xSupplier->removeSelectionChangeListener(xThis); + m_bListenerAdded = false; + } +} + +void SwXDispatch::selectionChanged( const lang::EventObject& ) +{ + ShellMode eMode = m_pView->GetShellMode(); + bool bEnable = ShellMode::Text == eMode || + ShellMode::ListText == eMode || + ShellMode::TableText == eMode || + ShellMode::TableListText == eMode; + if(bEnable == m_bOldEnable) + return; + + m_bOldEnable = bEnable; + frame::FeatureStateEvent aEvent; + aEvent.IsEnabled = bEnable; + aEvent.Source = getXWeak(); + + // calls to statusChanged may call addStatusListener or removeStatusListener + // so copy m_aStatusListenerVector on stack + auto copyStatusListenerVector = m_aStatusListenerVector; + for (auto & status : copyStatusListenerVector) + { + aEvent.FeatureURL = status.aURL; + if (status.aURL.Complete != cURLDocumentDataSource) + // the document's data source does not depend on the selection, so it's state does not change here + status.xListener->statusChanged( aEvent ); + } +} + +void SwXDispatch::disposing( const lang::EventObject& rSource ) +{ + uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY); + uno::Reference<view::XSelectionChangeListener> xThis = this; + xSupplier->removeSelectionChangeListener(xThis); + m_bListenerAdded = false; + + lang::EventObject aObject; + aObject.Source = getXWeak(); + // calls to statusChanged may call addStatusListener or removeStatusListener + // so copy m_aStatusListenerVector on stack + auto copyStatusListenerVector = m_aStatusListenerVector; + for (auto & status : copyStatusListenerVector) + { + status.xListener->disposing(aObject); + } + m_pView = nullptr; +} + +const char* SwXDispatch::GetDBChangeURL() +{ + return cInternalDBChangeNotification; +} + +SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::DispatchMutexLock_Impl() +{ +} + +SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::~DispatchMutexLock_Impl() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unodoc.cxx b/sw/source/uibase/uno/unodoc.cxx new file mode 100644 index 0000000000..b525d2e366 --- /dev/null +++ b/sw/source/uibase/uno/unodoc.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <config_features.h> +#include <config_fuzzers.h> + +#include <sfx2/sfxmodelfactory.hxx> +#include <swdll.hxx> +#include <docsh.hxx> +#include <globdoc.hxx> +#include <wdocsh.hxx> +#include <vcl/svapp.hxx> +#include <unomailmerge.hxx> + +using namespace ::com::sun::star; + +// com.sun.star.comp.Writer.TextDocument + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +Writer_SwTextDocument_get_implementation( + css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const& args) +{ + SolarMutexGuard aGuard; + SwGlobals::ensure(); + css::uno::Reference<css::uno::XInterface> xInterface = sfx2::createSfxModelInstance(args, + [](SfxModelFlags _nCreationFlags) + { + SfxObjectShell* pShell = new SwDocShell( _nCreationFlags ); + return pShell->GetModel(); + }); + xInterface->acquire(); + return xInterface.get(); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_Writer_WebDocument_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + SolarMutexGuard aGuard; + SwGlobals::ensure(); + SfxObjectShell* pShell = new SwWebDocShell; + uno::Reference< uno::XInterface > model( pShell->GetModel() ); + model->acquire(); + return model.get(); +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_Writer_GlobalDocument_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + SolarMutexGuard aGuard; + SwGlobals::ensure(); + SfxObjectShell* pShell = new SwGlobalDocShell( SfxObjectCreateMode::STANDARD ); + uno::Reference< uno::XInterface > model( pShell->GetModel() ); + model->acquire(); + return model.get(); +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +SwXMailMerge_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + SolarMutexGuard aGuard; + + //the module may not be loaded + SwGlobals::ensure(); + return cppu::acquire(new SwXMailMerge()); +#else + return nullptr; +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unomailmerge.cxx b/sw/source/uibase/uno/unomailmerge.cxx new file mode 100644 index 0000000000..2b5fecf21b --- /dev/null +++ b/sw/source/uibase/uno/unomailmerge.cxx @@ -0,0 +1,1168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/servicehelper.hxx> +#include <utility> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include <svl/itemprop.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <unotools/tempfile.hxx> +#include <sfx2/app.hxx> +#include <sfx2/docfilt.hxx> +#include <tools/urlobj.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/string.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/timer.hxx> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/text/MailMergeType.hpp> +#include <com/sun/star/text/MailMergeEvent.hpp> +#include <com/sun/star/text/XMailMergeListener.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/mail/XSmtpService.hpp> +#include <sfx2/viewfrm.hxx> +#include <sfx2/event.hxx> +#include <cppuhelper/implbase.hxx> +#include <printdata.hxx> +#include <swevent.hxx> +#include <unomailmerge.hxx> +#include <unoprnms.hxx> +#include <unomap.hxx> +#include <swunohelper.hxx> +#include <docsh.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <view.hxx> +#include <dbmgr.hxx> +#include <unotxdoc.hxx> +#include <wrtsh.hxx> +#include <mmconfigitem.hxx> +#include <mailmergehelper.hxx> + +#include <iodetect.hxx> + +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace SWUnoHelper; + +typedef ::utl::SharedUNOComponent< XInterface > SharedComponent; + +static osl::Mutex & GetMailMergeMutex() +{ + static osl::Mutex aMutex; + return aMutex; +} + +namespace { + +enum CloseResult +{ + eSuccess, // successfully closed + eVetoed, // vetoed, ownership transferred to the vetoing instance + eFailed // failed for some unknown reason +}; + +} + +static CloseResult CloseModelAndDocSh( + Reference< frame::XModel > const &rxModel, + SfxObjectShellRef &rxDocSh ) +{ + CloseResult eResult = eSuccess; + + rxDocSh = nullptr; + + //! models/documents should never be disposed (they may still be + //! used for printing which is called asynchronously for example) + //! instead call close + Reference< util::XCloseable > xClose( rxModel, UNO_QUERY ); + if (xClose.is()) + { + try + { + //! 'sal_True' -> transfer ownership to vetoing object if vetoed! + //! I.e. now that object is responsible for closing the model and doc shell. + xClose->close( true ); + } + catch (const util::CloseVetoException&) + { + //! here we have the problem that the temporary file that is + //! currently being printed will never be deleted. :-( + eResult = eVetoed; + } + catch (const uno::RuntimeException&) + { + eResult = eFailed; + } + } + return eResult; +} + +/// @throws RuntimeException +static bool LoadFromURL_impl( + Reference< frame::XModel > &rxModel, + SfxObjectShellRef &rxDocSh, + const OUString &rURL, + bool bClose ) +{ + // try to open the document readonly and hidden + Reference< frame::XModel > xTmpModel; + Sequence < PropertyValue > aArgs{ comphelper::makePropertyValue("Hidden", true) }; + try + { + Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() ); + xTmpModel.set( xDesktop->loadComponentFromURL( rURL, "_blank", 0, aArgs ), UNO_QUERY ); + } + catch (const Exception&) + { + return false; + } + + // try to get the DocShell + SwDocShell *pTmpDocShell = nullptr; + if (auto pTextDoc = comphelper::getFromUnoTunnel<SwXTextDocument>(xTmpModel); pTextDoc) + pTmpDocShell = pTextDoc->GetDocShell(); + + bool bRes = false; + if (xTmpModel.is() && pTmpDocShell) // everything available? + { + if (bClose) + CloseModelAndDocSh( rxModel, rxDocSh ); + // set new stuff + rxModel = xTmpModel; + rxDocSh = pTmpDocShell; + bRes = true; + } + else + { + // SfxObjectShellRef is ok here, since the document will be explicitly closed + SfxObjectShellRef xTmpDocSh = pTmpDocShell; + CloseModelAndDocSh( xTmpModel, xTmpDocSh ); + } + + return bRes; +} + +namespace +{ + class DelayedFileDeletion : public ::cppu::WeakImplHelper<util::XCloseListener> + { + protected: + ::osl::Mutex m_aMutex; + Reference< util::XCloseable > m_xDocument; + Timer m_aDeleteTimer; + OUString m_sTemporaryFile; + sal_Int32 m_nPendingDeleteAttempts; + + DelayedFileDeletion(DelayedFileDeletion const&) = delete; + DelayedFileDeletion& operator=(DelayedFileDeletion const&) = delete; + + public: + DelayedFileDeletion( const Reference< XModel >& _rxModel, + OUString _aTemporaryFile ); + + protected: + virtual ~DelayedFileDeletion( ) override; + + // XCloseListener + virtual void SAL_CALL queryClosing( const EventObject& _rSource, sal_Bool _bGetsOwnership ) override; + virtual void SAL_CALL notifyClosing( const EventObject& _rSource ) override; + + // XEventListener + virtual void SAL_CALL disposing( const EventObject& Source ) override; + + private: + void implTakeOwnership( ); + DECL_LINK( OnTryDeleteFile, Timer*, void ); + }; + + DelayedFileDeletion::DelayedFileDeletion( const Reference< XModel >& _rxModel, OUString _aTemporaryFile ) + : + m_xDocument( _rxModel, UNO_QUERY ) + ,m_aDeleteTimer("sw DelayedFileDeletion m_aDeleteTimer") + ,m_sTemporaryFile(std::move( _aTemporaryFile )) + ,m_nPendingDeleteAttempts( 0 ) + { + osl_atomic_increment( &m_refCount ); + try + { + if ( m_xDocument.is() ) + { + m_xDocument->addCloseListener( this ); + // successfully added -> keep ourself alive + acquire(); + } + else { + OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: model is no component!" ); + } + } + catch (const Exception&) + { + OSL_FAIL("DelayedFileDeletion::DelayedFileDeletion: could not register as event listener at the model!" ); + } + osl_atomic_decrement( &m_refCount ); + } + + IMPL_LINK_NOARG(DelayedFileDeletion, OnTryDeleteFile, Timer *, void) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + bool bSuccess = false; + try + { + bool bDeliverOwnership = ( 0 == m_nPendingDeleteAttempts ); + // if this is our last attempt, then anybody which vetoes this has to take the consequences + // (means take the ownership) + m_xDocument->close( bDeliverOwnership ); + bSuccess = true; + } + catch (const util::CloseVetoException&) + { + // somebody vetoed -> next try + if ( m_nPendingDeleteAttempts ) + { + // next attempt + --m_nPendingDeleteAttempts; + m_aDeleteTimer.Start(); + } + else + bSuccess = true; // can't do anything here ... + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "sw", "DelayedFileDeletion::OnTryDeleteFile: caught a strange exception!" ); + bSuccess = true; + // can't do anything here ... + } + + if ( bSuccess ) + { + SWUnoHelper::UCB_DeleteFile( m_sTemporaryFile ); + aGuard.clear(); + release(); // this should be our last reference, we should be dead after this + } + } + + void DelayedFileDeletion::implTakeOwnership( ) + { + // revoke ourself as listener + try + { + m_xDocument->removeCloseListener( this ); + } + catch (const Exception&) + { + OSL_FAIL("DelayedFileDeletion::implTakeOwnership: could not revoke the listener!" ); + } + + m_aDeleteTimer.SetTimeout( 3000 ); // 3 seconds + m_aDeleteTimer.SetInvokeHandler( LINK( this, DelayedFileDeletion, OnTryDeleteFile ) ); + m_nPendingDeleteAttempts = 3; // try 3 times at most + m_aDeleteTimer.Start( ); + } + + void SAL_CALL DelayedFileDeletion::queryClosing( const EventObject& , sal_Bool _bGetsOwnership ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( _bGetsOwnership ) + implTakeOwnership( ); + + // always veto: We want to take the ownership ourself, as this is the only chance to delete + // the temporary file which the model is based on + throw util::CloseVetoException( ); + } + + void SAL_CALL DelayedFileDeletion::notifyClosing( const EventObject& ) + { + OSL_FAIL("DelayedFileDeletion::notifyClosing: how this?" ); + // this should not happen: + // Either, a foreign instance closes the document, then we should veto this, and take the ownership + // Or, we ourself close the document, then we should not be a listener anymore + } + + void SAL_CALL DelayedFileDeletion::disposing( const EventObject& ) + { + OSL_FAIL("DelayedFileDeletion::disposing: how this?" ); + // this should not happen: + // Either, a foreign instance closes the document, then we should veto this, and take the ownership + // Or, we ourself close the document, then we should not be a listener anymore + } + + DelayedFileDeletion::~DelayedFileDeletion( ) + { + } +} + +static bool DeleteTmpFile_Impl( + Reference< frame::XModel > &rxModel, + SfxObjectShellRef &rxDocSh, + const OUString &rTmpFileURL ) +{ + bool bRes = false; + if (!rTmpFileURL.isEmpty()) + { + bool bDelete = true; + if ( eVetoed == CloseModelAndDocSh( rxModel, rxDocSh ) ) + { + // somebody vetoed the closing, and took the ownership of the document + // -> ensure that the temporary file is deleted later on + new DelayedFileDeletion( rxModel, rTmpFileURL ); + // note: as soon as #106931# is fixed, the whole DelayedFileDeletion is to be superseded by + // a better solution + bDelete = false; + } + + rxModel = nullptr; + rxDocSh = nullptr; // destroy doc shell + + if ( bDelete ) + { + if ( !SWUnoHelper::UCB_DeleteFile( rTmpFileURL ) ) + { + new DelayedFileDeletion( rxModel, rTmpFileURL ); + // same not as above: as soon as #106931#, ... + } + } + else + bRes = true; // file will be deleted delayed + } + return bRes; +} + +SwXMailMerge::SwXMailMerge() : + m_aEvtListeners ( GetMailMergeMutex() ), + m_aMergeListeners ( GetMailMergeMutex() ), + m_aPropListeners ( GetMailMergeMutex() ), + m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_MAILMERGE ) ), + m_nDataCommandType(sdb::CommandType::TABLE), + m_nOutputType(MailMergeType::PRINTER), + m_bEscapeProcessing(true), //!! allow to process properties like "Filter", "Order", ... + m_bSinglePrintJobs(false), + m_bFileNameFromColumn(false), + m_bSendAsHTML(false), + m_bSendAsAttachment(false), + m_bSaveAsSingleFile(false), + m_bDisposing(false), + m_pMgr(nullptr) +{ + // create empty document + // like in: SwModule::InsertEnv (appenv.cxx) + m_xDocSh = new SwDocShell( SfxObjectCreateMode::STANDARD ); + m_xDocSh->DoInitNew(); + SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *m_xDocSh, SFX_INTERFACE_NONE ); + SwView *pView = static_cast<SwView*>( pFrame->GetViewShell() ); + pView->AttrChangedNotify(nullptr); //So that SelectShell is called. + m_xModel = m_xDocSh->GetModel(); +} + +SwXMailMerge::~SwXMailMerge() +{ + if (!m_aTmpFileName.isEmpty()) + DeleteTmpFile_Impl( m_xModel, m_xDocSh, m_aTmpFileName ); + else // there was no temporary file in use + { + //! we still need to close the model and doc shell manually + //! because there is no automatism that will do that later. + //! #120086# + if ( eVetoed == CloseModelAndDocSh( m_xModel, m_xDocSh ) ) + OSL_FAIL("ownership transferred to vetoing object!" ); + + m_xModel = nullptr; + m_xDocSh = nullptr; // destroy doc shell + } +} + +// Guarantee object consistence in case of an exception +class MailMergeExecuteFinalizer +{ +public: + explicit MailMergeExecuteFinalizer(SwXMailMerge *mailmerge) + : m_pMailMerge(mailmerge) + { + assert(m_pMailMerge); //mailmerge object missing + } + ~MailMergeExecuteFinalizer() + { + osl::MutexGuard aMgrGuard( GetMailMergeMutex() ); + m_pMailMerge->m_pMgr = nullptr; + } + +private: + MailMergeExecuteFinalizer(MailMergeExecuteFinalizer const&) = delete; + MailMergeExecuteFinalizer& operator=(MailMergeExecuteFinalizer const&) = delete; + + SwXMailMerge *m_pMailMerge; +}; + +uno::Any SAL_CALL SwXMailMerge::execute( + const uno::Sequence< beans::NamedValue >& rArguments ) +{ + SolarMutexGuard aGuard; + MailMergeExecuteFinalizer aFinalizer(this); + + // get property values to be used + // (use values from the service as default and override them with + // the values that are provided as arguments) + + uno::Sequence< uno::Any > aCurSelection = m_aSelection; + uno::Reference< sdbc::XResultSet > xCurResultSet = m_xResultSet; + uno::Reference< sdbc::XConnection > xCurConnection = m_xConnection; + uno::Reference< frame::XModel > xCurModel = m_xModel; + OUString aCurDataSourceName = m_aDataSourceName; + OUString aCurDataCommand = m_aDataCommand; + OUString aCurFilter = m_aFilter; + OUString aCurDocumentURL = m_aDocumentURL; + OUString aCurOutputURL = m_aOutputURL; + OUString aCurFileNamePrefix = m_aFileNamePrefix; + sal_Int32 nCurDataCommandType = m_nDataCommandType; + sal_Int16 nCurOutputType = m_nOutputType; + bool bCurEscapeProcessing = m_bEscapeProcessing; + bool bCurSinglePrintJobs = m_bSinglePrintJobs; + bool bCurFileNameFromColumn = m_bFileNameFromColumn; + + SfxObjectShellRef xCurDocSh = m_xDocSh; // the document + + for (const beans::NamedValue& rArgument : rArguments) + { + const OUString &rName = rArgument.Name; + const Any &rValue = rArgument.Value; + + bool bOK = true; + if (rName == UNO_NAME_SELECTION) + bOK = rValue >>= aCurSelection; + else if (rName == UNO_NAME_RESULT_SET) + bOK = rValue >>= xCurResultSet; + else if (rName == UNO_NAME_CONNECTION) + bOK = rValue >>= xCurConnection; + else if (rName == UNO_NAME_MODEL) + throw PropertyVetoException("Property is read-only: " + rName, getXWeak() ); + else if (rName == UNO_NAME_DATA_SOURCE_NAME) + bOK = rValue >>= aCurDataSourceName; + else if (rName == UNO_NAME_DAD_COMMAND) + bOK = rValue >>= aCurDataCommand; + else if (rName == UNO_NAME_FILTER) + bOK = rValue >>= aCurFilter; + else if (rName == UNO_NAME_DOCUMENT_URL) + { + bOK = rValue >>= aCurDocumentURL; + if (!aCurDocumentURL.isEmpty() + && !LoadFromURL_impl( xCurModel, xCurDocSh, aCurDocumentURL, false )) + throw RuntimeException("Failed to create document from URL: " + aCurDocumentURL, getXWeak() ); + } + else if (rName == UNO_NAME_OUTPUT_URL) + { + bOK = rValue >>= aCurOutputURL; + if (!aCurOutputURL.isEmpty()) + { + if (!UCB_IsDirectory(aCurOutputURL)) + throw IllegalArgumentException("URL does not point to a directory: " + aCurOutputURL, getXWeak(), 0 ); + if (UCB_IsReadOnlyFileName(aCurOutputURL)) + throw IllegalArgumentException("URL is read-only: " + aCurOutputURL, getXWeak(), 0 ); + } + } + else if (rName == UNO_NAME_FILE_NAME_PREFIX) + bOK = rValue >>= aCurFileNamePrefix; + else if (rName == UNO_NAME_DAD_COMMAND_TYPE) + bOK = rValue >>= nCurDataCommandType; + else if (rName == UNO_NAME_OUTPUT_TYPE) + bOK = rValue >>= nCurOutputType; + else if (rName == UNO_NAME_ESCAPE_PROCESSING) + bOK = rValue >>= bCurEscapeProcessing; + else if (rName == UNO_NAME_SINGLE_PRINT_JOBS) + bOK = rValue >>= bCurSinglePrintJobs; + else if (rName == UNO_NAME_FILE_NAME_FROM_COLUMN) + bOK = rValue >>= bCurFileNameFromColumn; + else if (rName == UNO_NAME_SUBJECT) + bOK = rValue >>= m_sSubject; + else if (rName == UNO_NAME_ADDRESS_FROM_COLUMN) + bOK = rValue >>= m_sAddressFromColumn; + else if (rName == UNO_NAME_SEND_AS_HTML) + bOK = rValue >>= m_bSendAsHTML; + else if (rName == UNO_NAME_MAIL_BODY) + bOK = rValue >>= m_sMailBody; + else if (rName == UNO_NAME_ATTACHMENT_NAME) + bOK = rValue >>= m_sAttachmentName; + else if (rName == UNO_NAME_ATTACHMENT_FILTER) + bOK = rValue >>= m_sAttachmentFilter; + else if (rName == UNO_NAME_COPIES_TO) + bOK = rValue >>= m_aCopiesTo; + else if (rName == UNO_NAME_BLIND_COPIES_TO) + bOK = rValue >>= m_aBlindCopiesTo; + else if (rName == UNO_NAME_SEND_AS_ATTACHMENT) + bOK = rValue >>= m_bSendAsAttachment; + else if (rName == UNO_NAME_PRINT_OPTIONS) + bOK = rValue >>= m_aPrintSettings; + else if (rName == UNO_NAME_SAVE_AS_SINGLE_FILE) + bOK = rValue >>= m_bSaveAsSingleFile; + else if (rName == UNO_NAME_SAVE_FILTER) + bOK = rValue >>= m_sSaveFilter; + else if (rName == UNO_NAME_SAVE_FILTER_OPTIONS) + bOK = rValue >>= m_sSaveFilterOptions; + else if (rName == UNO_NAME_SAVE_FILTER_DATA) + bOK = rValue >>= m_aSaveFilterData; + else if (rName == UNO_NAME_IN_SERVER_PASSWORD) + bOK = rValue >>= m_sInServerPassword; + else if (rName == UNO_NAME_OUT_SERVER_PASSWORD) + bOK = rValue >>= m_sOutServerPassword; + else + throw UnknownPropertyException( "Property is unknown: " + rName, getXWeak() ); + + if (!bOK) + throw IllegalArgumentException("Property type mismatch or property not set: " + rName, getXWeak(), 0 ); + } + + // need to translate the selection: the API here requires a sequence of bookmarks, but the Merge + // method we will call below requires a sequence of indices. + if ( aCurSelection.hasElements() ) + { + Sequence< Any > aTranslated( aCurSelection.getLength() ); + + bool bValid = false; + Reference< sdbcx::XRowLocate > xRowLocate( xCurResultSet, UNO_QUERY ); + if ( xRowLocate.is() ) + { + Any* pTranslated = aTranslated.getArray(); + + try + { + bool bEverythingsFine = true; + for ( const Any& rBookmark : std::as_const(aCurSelection) ) + { + bEverythingsFine = xRowLocate->moveToBookmark( rBookmark ); + if ( !bEverythingsFine ) + break; + *pTranslated <<= xCurResultSet->getRow(); + ++pTranslated; + } + if ( bEverythingsFine ) + bValid = true; + } + catch (const Exception&) + { + bValid = false; + } + } + + if ( !bValid ) + { + throw IllegalArgumentException( + "The current 'Selection' does not describe a valid array of bookmarks, relative to the current 'ResultSet'.", + getXWeak(), + 0 + ); + } + + aCurSelection = aTranslated; + } + + SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xCurDocSh.get(), false); + SwView *pView = pFrame ? dynamic_cast<SwView*>( pFrame->GetViewShell() ) : nullptr; + if (!pView) + throw RuntimeException(); + + // avoid assertion in 'Update' from Sfx by supplying a shell + // and thus avoiding the SelectShell call in Writers GetState function + // while still in Update of Sfx. + // (GetSelection in Update is not allowed) + if (!aCurDocumentURL.isEmpty()) + pView->AttrChangedNotify(nullptr);//So that SelectShell is called. + + SharedComponent aRowSetDisposeHelper; + if (!xCurResultSet.is()) + { + if (aCurDataSourceName.isEmpty() || aCurDataCommand.isEmpty() ) + { + OSL_FAIL("PropertyValues missing or unset"); + throw IllegalArgumentException("Either the ResultSet or DataSourceName and DataCommand must be set.", getXWeak(), 0 ); + } + + // build ResultSet from DataSourceName, DataCommand and DataCommandType + + Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); + if (xMgr.is()) + { + Reference< XInterface > xInstance = xMgr->createInstance( "com.sun.star.sdb.RowSet" ); + aRowSetDisposeHelper.reset( xInstance, SharedComponent::TakeOwnership ); + Reference< XPropertySet > xRowSetPropSet( xInstance, UNO_QUERY ); + OSL_ENSURE( xRowSetPropSet.is(), "failed to get XPropertySet interface from RowSet" ); + if (xRowSetPropSet.is()) + { + if (xCurConnection.is()) + xRowSetPropSet->setPropertyValue( "ActiveConnection", Any( xCurConnection ) ); + xRowSetPropSet->setPropertyValue( "DataSourceName", Any( aCurDataSourceName ) ); + xRowSetPropSet->setPropertyValue( "Command", Any( aCurDataCommand ) ); + xRowSetPropSet->setPropertyValue( "CommandType", Any( nCurDataCommandType ) ); + xRowSetPropSet->setPropertyValue( "EscapeProcessing", Any( bCurEscapeProcessing ) ); + xRowSetPropSet->setPropertyValue( "ApplyFilter", Any( true ) ); + xRowSetPropSet->setPropertyValue( "Filter", Any( aCurFilter ) ); + + Reference< sdbc::XRowSet > xRowSet( xInstance, UNO_QUERY ); + if (xRowSet.is()) + xRowSet->execute(); // build ResultSet from properties + if( !xCurConnection.is() ) + xCurConnection.set( xRowSetPropSet->getPropertyValue( "ActiveConnection" ), UNO_QUERY ); + xCurResultSet = xRowSet; + OSL_ENSURE( xCurResultSet.is(), "failed to build ResultSet" ); + } + } + } + + svx::ODataAccessDescriptor aDescriptor; + aDescriptor.setDataSource(aCurDataSourceName); + aDescriptor[ svx::DataAccessDescriptorProperty::Connection ] <<= xCurConnection; + aDescriptor[ svx::DataAccessDescriptorProperty::Command ] <<= aCurDataCommand; + aDescriptor[ svx::DataAccessDescriptorProperty::CommandType ] <<= nCurDataCommandType; + aDescriptor[ svx::DataAccessDescriptorProperty::EscapeProcessing ] <<= bCurEscapeProcessing; + aDescriptor[ svx::DataAccessDescriptorProperty::Cursor ] <<= xCurResultSet; + // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnName ] not used + // aDescriptor[ svx::DataAccessDescriptorProperty::ColumnObject ] not used + aDescriptor[ svx::DataAccessDescriptorProperty::Selection ] <<= aCurSelection; + + DBManagerOptions nMergeType; + switch (nCurOutputType) + { + case MailMergeType::PRINTER : nMergeType = DBMGR_MERGE_PRINTER; break; + case MailMergeType::FILE : nMergeType = DBMGR_MERGE_FILE; break; + case MailMergeType::MAIL : nMergeType = DBMGR_MERGE_EMAIL; break; + case MailMergeType::SHELL : nMergeType = DBMGR_MERGE_SHELL; break; + default: + throw IllegalArgumentException("Invalid value of property: OutputType", getXWeak(), 0 ); + } + + SwWrtShell &rSh = pView->GetWrtShell(); + SwDBManager* pMgr = rSh.GetDBManager(); + //force layout creation + rSh.CalcLayout(); + OSL_ENSURE( pMgr, "database manager missing" ); + m_pMgr = pMgr; + + SwMergeDescriptor aMergeDesc( nMergeType, rSh, aDescriptor ); + + std::unique_ptr< SwMailMergeConfigItem > pMMConfigItem; + uno::Reference< mail::XMailService > xInService; + switch (nCurOutputType) + { + case MailMergeType::PRINTER: + { + IDocumentDeviceAccess& rIDDA = rSh.getIDocumentDeviceAccess(); + SwPrintData aPrtData( rIDDA.getPrintData() ); + aPrtData.SetPrintSingleJobs( bCurSinglePrintJobs ); + rIDDA.setPrintData( aPrtData ); + // #i25686# printing should not be done asynchronously to prevent dangling offices + // when mail merge is called as command line macro + aMergeDesc.aPrintOptions = m_aPrintSettings; + aMergeDesc.bCreateSingleFile = true; + } + break; + case MailMergeType::SHELL: + aMergeDesc.bCreateSingleFile = true; + pMMConfigItem.reset(new SwMailMergeConfigItem); + aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get(); + break; + case MailMergeType::FILE: + { + INetURLObject aURLObj; + aURLObj.SetSmartProtocol( INetProtocol::File ); + + if (!aCurDocumentURL.isEmpty()) + { + // if OutputURL or FileNamePrefix are missing get + // them from DocumentURL + aURLObj.SetSmartURL( aCurDocumentURL ); + if (aCurFileNamePrefix.isEmpty()) + aCurFileNamePrefix = aURLObj.GetBase(); // filename without extension + if (aCurOutputURL.isEmpty()) + { + aURLObj.removeSegment(); + aCurOutputURL = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + } + } + else // default empty document without URL + { + if (aCurOutputURL.isEmpty()) + throw RuntimeException("OutputURL is not set and can not be obtained.", getXWeak() ); + } + + aURLObj.SetSmartURL( aCurOutputURL ); + OUString aPath = aURLObj.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + + static constexpr OUString aDelim( u"/"_ustr ); + if (!aPath.isEmpty() && !aPath.endsWith(aDelim)) + aPath += aDelim; + if (bCurFileNameFromColumn) + aMergeDesc.sDBcolumn = aCurFileNamePrefix; + else + { + aPath += aCurFileNamePrefix; + } + + aMergeDesc.sPrefix = aPath; + aMergeDesc.sSaveToFilter = m_sSaveFilter; + aMergeDesc.sSaveToFilterOptions = m_sSaveFilterOptions; + aMergeDesc.aSaveToFilterData = m_aSaveFilterData; + aMergeDesc.bCreateSingleFile = m_bSaveAsSingleFile; + } + break; + case MailMergeType::MAIL: + { + aMergeDesc.sDBcolumn = m_sAddressFromColumn; + if(m_sAddressFromColumn.isEmpty()) + throw RuntimeException("Mail address column not set.", getXWeak() ); + aMergeDesc.sSaveToFilter = m_sAttachmentFilter; + aMergeDesc.sSubject = m_sSubject; + aMergeDesc.sMailBody = m_sMailBody; + aMergeDesc.sAttachmentName = m_sAttachmentName; + aMergeDesc.aCopiesTo = m_aCopiesTo; + aMergeDesc.aBlindCopiesTo = m_aBlindCopiesTo; + aMergeDesc.bSendAsHTML = m_bSendAsHTML; + aMergeDesc.bSendAsAttachment = m_bSendAsAttachment; + + aMergeDesc.bCreateSingleFile = false; + pMMConfigItem.reset(new SwMailMergeConfigItem); + aMergeDesc.pMailMergeConfigItem = pMMConfigItem.get(); + aMergeDesc.xSmtpServer = SwMailMergeHelper::ConnectToSmtpServer( + *pMMConfigItem, + xInService, + m_sInServerPassword, m_sOutServerPassword ); + if( !aMergeDesc.xSmtpServer.is() || !aMergeDesc.xSmtpServer->isConnected()) + throw RuntimeException("Failed to connect to mail server.", getXWeak() ); + } + break; + } + + // save document with temporary filename + std::shared_ptr<const SfxFilter> pSfxFlt = SwIoSystem::GetFilterOfFormat( + FILTER_XML, + SwDocShell::Factory().GetFilterContainer() ); + OUString aExtension(comphelper::string::stripStart(pSfxFlt->GetDefaultExtension(), '*')); + m_aTmpFileName = utl::CreateTempURL( u"SwMM", true, aExtension ); + + Reference< XStorable > xStorable( xCurModel, UNO_QUERY ); + bool bStoredAsTemporary = false; + if ( xStorable.is() ) + { + try + { + xStorable->storeAsURL( m_aTmpFileName, Sequence< PropertyValue >() ); + bStoredAsTemporary = true; + } + catch (const Exception&) + { + } + } + if ( !bStoredAsTemporary ) + throw RuntimeException("Failed to save temporary file.", getXWeak() ); + + pMgr->SetMergeSilent( true ); // suppress dialogs, message boxes, etc. + const SwXMailMerge *pOldSrc = pMgr->GetMailMergeEvtSrc(); + OSL_ENSURE( !pOldSrc || pOldSrc == this, "Ooops... different event source already set." ); + pMgr->SetMailMergeEvtSrc( this ); // launch events for listeners + + SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMerge, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xCurDocSh.get())); + bool bSucc = pMgr->Merge( aMergeDesc ); + SfxGetpApp()->NotifyEvent(SfxEventHint(SfxEventHintId::SwMailMergeEnd, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), xCurDocSh.get())); + + pMgr->SetMailMergeEvtSrc( pOldSrc ); + + if ( xCurModel.get() != m_xModel.get() ) + { // in case it was a temporary model -> close it, and delete the file + DeleteTmpFile_Impl( xCurModel, xCurDocSh, m_aTmpFileName ); + m_aTmpFileName.clear(); + } + // (in case it wasn't a temporary model, it will be closed in the dtor, at the latest) + + if (!bSucc) + throw Exception("Mail merge failed. Sorry, no further information available.", getXWeak() ); + + //de-initialize services + if(xInService.is() && xInService->isConnected()) + xInService->disconnect(); + if(aMergeDesc.xSmtpServer.is() && aMergeDesc.xSmtpServer->isConnected()) + aMergeDesc.xSmtpServer->disconnect(); + + if (DBMGR_MERGE_SHELL == nMergeType) + { + return Any( aMergeDesc.pMailMergeConfigItem->GetTargetView()->GetDocShell()->GetBaseModel() ); + } + else + return Any( true ); +} + +void SAL_CALL SwXMailMerge::cancel() +{ + // Cancel may be called from a second thread, so this protects from m_pMgr + /// cleanup in the execute function. + osl::MutexGuard aMgrGuard( GetMailMergeMutex() ); + if (m_pMgr) + m_pMgr->MergeCancel(); +} + +void SwXMailMerge::LaunchMailMergeEvent( const MailMergeEvent &rEvt ) const +{ + comphelper::OInterfaceIteratorHelper2 aIt( const_cast<SwXMailMerge *>(this)->m_aMergeListeners ); + while (aIt.hasMoreElements()) + { + static_cast< XMailMergeListener* >( aIt.next() )->notifyMailMergeEvent( rEvt ); + } +} + +void SwXMailMerge::launchEvent( const PropertyChangeEvent &rEvt ) const +{ + comphelper::OInterfaceContainerHelper3<XPropertyChangeListener> *pContainer = + m_aPropListeners.getContainer( rEvt.PropertyHandle ); + if (pContainer) + { + pContainer->notifyEach( &XPropertyChangeListener::propertyChange, rEvt ); + } +} + +uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXMailMerge::getPropertySetInfo( ) +{ + SolarMutexGuard aGuard; + static Reference< XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo(); + return aRef; +} + +void SAL_CALL SwXMailMerge::setPropertyValue( + const OUString& rPropertyName, const uno::Any& rValue ) +{ + SolarMutexGuard aGuard; + + const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pCur) + throw UnknownPropertyException(rPropertyName); + else if (pCur->nFlags & PropertyAttribute::READONLY) + throw PropertyVetoException(); + else + { + void *pData = nullptr; + switch (pCur->nWID) + { + case WID_SELECTION : pData = &m_aSelection; break; + case WID_RESULT_SET : pData = &m_xResultSet; break; + case WID_CONNECTION : pData = &m_xConnection; break; + case WID_MODEL : pData = &m_xModel; break; + case WID_DATA_SOURCE_NAME : pData = &m_aDataSourceName; break; + case WID_DATA_COMMAND : pData = &m_aDataCommand; break; + case WID_FILTER : pData = &m_aFilter; break; + case WID_DOCUMENT_URL : pData = &m_aDocumentURL; break; + case WID_OUTPUT_URL : pData = &m_aOutputURL; break; + case WID_DATA_COMMAND_TYPE : pData = &m_nDataCommandType; break; + case WID_OUTPUT_TYPE : pData = &m_nOutputType; break; + case WID_ESCAPE_PROCESSING : pData = &m_bEscapeProcessing; break; + case WID_SINGLE_PRINT_JOBS : pData = &m_bSinglePrintJobs; break; + case WID_FILE_NAME_FROM_COLUMN : pData = &m_bFileNameFromColumn; break; + case WID_FILE_NAME_PREFIX : pData = &m_aFileNamePrefix; break; + case WID_MAIL_SUBJECT: pData = &m_sSubject; break; + case WID_ADDRESS_FROM_COLUMN: pData = &m_sAddressFromColumn; break; + case WID_SEND_AS_HTML: pData = &m_bSendAsHTML; break; + case WID_SEND_AS_ATTACHMENT: pData = &m_bSendAsAttachment; break; + case WID_MAIL_BODY: pData = &m_sMailBody; break; + case WID_ATTACHMENT_NAME: pData = &m_sAttachmentName; break; + case WID_ATTACHMENT_FILTER: pData = &m_sAttachmentFilter;break; + case WID_PRINT_OPTIONS: pData = &m_aPrintSettings; break; + case WID_SAVE_AS_SINGLE_FILE: pData = &m_bSaveAsSingleFile; break; + case WID_SAVE_FILTER: pData = &m_sSaveFilter; break; + case WID_SAVE_FILTER_OPTIONS: pData = &m_sSaveFilterOptions; break; + case WID_SAVE_FILTER_DATA: pData = &m_aSaveFilterData; break; + case WID_COPIES_TO: pData = &m_aCopiesTo; break; + case WID_BLIND_COPIES_TO: pData = &m_aBlindCopiesTo;break; + case WID_IN_SERVER_PASSWORD: pData = &m_sInServerPassword; break; + case WID_OUT_SERVER_PASSWORD: pData = &m_sOutServerPassword; break; + default : + OSL_FAIL("unknown WID"); + } + Any aOld( pData, pCur->aType ); + + bool bChanged = false; + bool bOK = true; + if (aOld != rValue) + { + if (pData == &m_aSelection) + bOK = rValue >>= m_aSelection; + else if (pData == &m_xResultSet) + bOK = rValue >>= m_xResultSet; + else if (pData == &m_xConnection) + bOK = rValue >>= m_xConnection; + else if (pData == &m_xModel) + bOK = rValue >>= m_xModel; + else if (pData == &m_aDataSourceName) + bOK = rValue >>= m_aDataSourceName; + else if (pData == &m_aDataCommand) + bOK = rValue >>= m_aDataCommand; + else if (pData == &m_aFilter) + bOK = rValue >>= m_aFilter; + else if (pData == &m_aDocumentURL) + { + OUString aText; + bOK = rValue >>= aText; + if (!aText.isEmpty() + && !LoadFromURL_impl( m_xModel, m_xDocSh, aText, true )) + throw RuntimeException("Failed to create document from URL: " + aText, getXWeak() ); + m_aDocumentURL = aText; + } + else if (pData == &m_aOutputURL) + { + OUString aText; + bOK = rValue >>= aText; + if (!aText.isEmpty()) + { + if (!UCB_IsDirectory(aText)) + throw IllegalArgumentException("URL does not point to a directory: " + aText, getXWeak(), 0 ); + if (UCB_IsReadOnlyFileName(aText)) + throw IllegalArgumentException("URL is read-only: " + aText, getXWeak(), 0 ); + } + m_aOutputURL = aText; + } + else if (pData == &m_nDataCommandType) + bOK = rValue >>= m_nDataCommandType; + else if (pData == &m_nOutputType) + bOK = rValue >>= m_nOutputType; + else if (pData == &m_bEscapeProcessing) + bOK = rValue >>= m_bEscapeProcessing; + else if (pData == &m_bSinglePrintJobs) + bOK = rValue >>= m_bSinglePrintJobs; + else if (pData == &m_bFileNameFromColumn) + bOK = rValue >>= m_bFileNameFromColumn; + else if (pData == &m_aFileNamePrefix) + bOK = rValue >>= m_aFileNamePrefix; + else if (pData == &m_sSubject) + bOK = rValue >>= m_sSubject; + else if (pData == &m_sAddressFromColumn) + bOK = rValue >>= m_sAddressFromColumn; + else if (pData == &m_bSendAsHTML) + bOK = rValue >>= m_bSendAsHTML; + else if (pData == &m_bSendAsAttachment) + bOK = rValue >>= m_bSendAsAttachment; + else if (pData == &m_sMailBody) + bOK = rValue >>= m_sMailBody; + else if (pData == &m_sAttachmentName) + bOK = rValue >>= m_sAttachmentName; + else if (pData == &m_sAttachmentFilter) + bOK = rValue >>= m_sAttachmentFilter; + else if (pData == &m_aPrintSettings) + bOK = rValue >>= m_aPrintSettings; + else if (pData == &m_bSaveAsSingleFile) + bOK = rValue >>= m_bSaveAsSingleFile; + else if (pData == &m_sSaveFilter) + bOK = rValue >>= m_sSaveFilter; + else if (pData == &m_sSaveFilterOptions) + bOK = rValue >>= m_sSaveFilterOptions; + else if (pData == &m_aSaveFilterData) + bOK = rValue >>= m_aSaveFilterData; + else if (pData == &m_aCopiesTo) + bOK = rValue >>= m_aCopiesTo; + else if (pData == &m_aBlindCopiesTo) + bOK = rValue >>= m_aBlindCopiesTo; + else if(pData == &m_sInServerPassword) + bOK = rValue >>= m_sInServerPassword; + else if(pData == &m_sOutServerPassword) + bOK = rValue >>= m_sOutServerPassword; + else { + OSL_FAIL("invalid pointer" ); + } + OSL_ENSURE( bOK, "set value failed" ); + bChanged = true; + } + if (!bOK) + throw IllegalArgumentException("Property type mismatch or property not set: " + rPropertyName, getXWeak(), 0 ); + + if (bChanged) + { + PropertyChangeEvent aChgEvt( static_cast<XPropertySet *>(this), rPropertyName, + false, pCur->nWID, aOld, rValue ); + launchEvent( aChgEvt ); + } + } +} + +uno::Any SAL_CALL SwXMailMerge::getPropertyValue( + const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + + Any aRet; + + const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pCur) + throw UnknownPropertyException(rPropertyName); + + switch (pCur->nWID) + { + case WID_SELECTION : aRet <<= m_aSelection; break; + case WID_RESULT_SET : aRet <<= m_xResultSet; break; + case WID_CONNECTION : aRet <<= m_xConnection; break; + case WID_MODEL : aRet <<= m_xModel; break; + case WID_DATA_SOURCE_NAME : aRet <<= m_aDataSourceName; break; + case WID_DATA_COMMAND : aRet <<= m_aDataCommand; break; + case WID_FILTER : aRet <<= m_aFilter; break; + case WID_DOCUMENT_URL : aRet <<= m_aDocumentURL; break; + case WID_OUTPUT_URL : aRet <<= m_aOutputURL; break; + case WID_DATA_COMMAND_TYPE : aRet <<= m_nDataCommandType; break; + case WID_OUTPUT_TYPE : aRet <<= m_nOutputType; break; + case WID_ESCAPE_PROCESSING : aRet <<= m_bEscapeProcessing; break; + case WID_SINGLE_PRINT_JOBS : aRet <<= m_bSinglePrintJobs; break; + case WID_FILE_NAME_FROM_COLUMN : aRet <<= m_bFileNameFromColumn; break; + case WID_FILE_NAME_PREFIX : aRet <<= m_aFileNamePrefix; break; + case WID_MAIL_SUBJECT: aRet <<= m_sSubject; break; + case WID_ADDRESS_FROM_COLUMN: aRet <<= m_sAddressFromColumn; break; + case WID_SEND_AS_HTML: aRet <<= m_bSendAsHTML; break; + case WID_SEND_AS_ATTACHMENT: aRet <<= m_bSendAsAttachment; break; + case WID_MAIL_BODY: aRet <<= m_sMailBody; break; + case WID_ATTACHMENT_NAME: aRet <<= m_sAttachmentName; break; + case WID_ATTACHMENT_FILTER: aRet <<= m_sAttachmentFilter;break; + case WID_PRINT_OPTIONS: aRet <<= m_aPrintSettings; break; + case WID_SAVE_AS_SINGLE_FILE: aRet <<= m_bSaveAsSingleFile; break; + case WID_SAVE_FILTER: aRet <<= m_sSaveFilter; break; + case WID_SAVE_FILTER_OPTIONS: aRet <<= m_sSaveFilterOptions; break; + case WID_SAVE_FILTER_DATA: aRet <<= m_aSaveFilterData; break; + case WID_COPIES_TO: aRet <<= m_aCopiesTo; break; + case WID_BLIND_COPIES_TO: aRet <<= m_aBlindCopiesTo;break; + case WID_IN_SERVER_PASSWORD: aRet <<= m_sInServerPassword; break; + case WID_OUT_SERVER_PASSWORD: aRet <<= m_sOutServerPassword; break; + default : + OSL_FAIL("unknown WID"); + } + + return aRet; +} + +void SAL_CALL SwXMailMerge::addPropertyChangeListener( + const OUString& rPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& rListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rListener.is()) + { + const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pCur) + throw UnknownPropertyException(rPropertyName); + m_aPropListeners.addInterface( pCur->nWID, rListener ); + } +} + +void SAL_CALL SwXMailMerge::removePropertyChangeListener( + const OUString& rPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& rListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rListener.is()) + { + const SfxItemPropertyMapEntry* pCur = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pCur) + throw UnknownPropertyException(rPropertyName); + m_aPropListeners.removeInterface( pCur->nWID, rListener ); + } +} + +void SAL_CALL SwXMailMerge::addVetoableChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ ) +{ + // no vetoable property, thus no support for vetoable change listeners + OSL_FAIL("not implemented"); +} + +void SAL_CALL SwXMailMerge::removeVetoableChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*rListener*/ ) +{ + // no vetoable property, thus no support for vetoable change listeners + OSL_FAIL("not implemented"); +} + +void SAL_CALL SwXMailMerge::dispose() +{ + SolarMutexGuard aGuard; + + if (!m_bDisposing) + { + m_bDisposing = true; + + EventObject aEvtObj( static_cast<XPropertySet *>(this) ); + m_aEvtListeners.disposeAndClear( aEvtObj ); + m_aMergeListeners.disposeAndClear( aEvtObj ); + m_aPropListeners.disposeAndClear( aEvtObj ); + } +} + +void SAL_CALL SwXMailMerge::addEventListener( + const Reference< XEventListener >& rxListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rxListener.is()) + m_aEvtListeners.addInterface( rxListener ); +} + +void SAL_CALL SwXMailMerge::removeEventListener( + const Reference< XEventListener >& rxListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rxListener.is()) + m_aEvtListeners.removeInterface( rxListener ); +} + +void SAL_CALL SwXMailMerge::addMailMergeEventListener( + const uno::Reference< XMailMergeListener >& rxListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rxListener.is()) + m_aMergeListeners.addInterface( rxListener ); +} + +void SAL_CALL SwXMailMerge::removeMailMergeEventListener( + const uno::Reference< XMailMergeListener >& rxListener ) +{ + SolarMutexGuard aGuard; + if (!m_bDisposing && rxListener.is()) + m_aMergeListeners.removeInterface( rxListener ); +} + +OUString SAL_CALL SwXMailMerge::getImplementationName() +{ + return "SwXMailMerge"; +} + +sal_Bool SAL_CALL SwXMailMerge::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SAL_CALL SwXMailMerge::getSupportedServiceNames() +{ + return { "com.sun.star.text.MailMerge", "com.sun.star.sdb.DataAccessDescriptor" }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unomod.cxx b/sw/source/uibase/uno/unomod.cxx new file mode 100644 index 0000000000..63250ede85 --- /dev/null +++ b/sw/source/uibase/uno/unomod.cxx @@ -0,0 +1,976 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/view/DocumentZoomType.hpp> +#include <comphelper/ChainablePropertySetInfo.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/any.hxx> +#include <osl/diagnose.h> +#include <svl/itemprop.hxx> +#include <tools/urlobj.hxx> +#include <tools/UnitConversion.hxx> +#include <vcl/svapp.hxx> + +#include <unomod.hxx> +#include <usrpref.hxx> +#include <prtopt.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <viewopt.hxx> +#include <doc.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <edtwin.hxx> +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::comphelper; + +namespace { + +enum SwViewSettingsPropertyHandles +{ + HANDLE_VIEWSET_ANNOTATIONS, + HANDLE_VIEWSET_BREAKS, + HANDLE_VIEWSET_DRAWINGS, + HANDLE_VIEWSET_FIELD_COMMANDS, + HANDLE_VIEWSET_FOOTNOTE_BACKGROUND, + HANDLE_VIEWSET_GRAPHICS, + HANDLE_VIEWSET_HIDDEN_CHARACTERS, + HANDLE_VIEWSET_HIDDEN_PARAGRAPHS, + HANDLE_VIEWSET_HIDDEN_TEXT, + HANDLE_VIEWSET_HRULER, + HANDLE_VIEWSET_HSCROLL, + HANDLE_VIEWSET_INDEX_MARK_BACKGROUND, + HANDLE_VIEWSET_NONPRINTING_CHARACTERS, + HANDLE_VIEWSET_ONLINE_LAYOUT, + HANDLE_VIEWSET_PARA_BREAKS, + HANDLE_VIEWSET_PROTECTED_SPACES, + HANDLE_VIEWSET_SOFT_HYPHENS, + HANDLE_VIEWSET_SPACES, + HANDLE_VIEWSET_TABLE_BOUNDARIES, + HANDLE_VIEWSET_TABLES, + HANDLE_VIEWSET_TABSTOPS, + HANDLE_VIEWSET_TEXT_BOUNDARIES, + HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND, + HANDLE_VIEWSET_VRULER, + HANDLE_VIEWSET_VSCROLL, + HANDLE_VIEWSET_SMOOTH_SCROLLING, + HANDLE_VIEWSET_ZOOM_TYPE, + HANDLE_VIEWSET_ZOOM, + HANDLE_VIEWSET_SHOW_CONTENT_TIPS, + HANDLE_VIEWSET_HELP_URL, + HANDLE_VIEWSET_VRULER_RIGHT, + HANDLE_VIEWSET_SHOW_RULER, + HANDLE_VIEWSET_IS_RASTER_VISIBLE, + HANDLE_VIEWSET_IS_SNAP_TO_RASTER, + HANDLE_VIEWSET_RASTER_RESOLUTION_X, + HANDLE_VIEWSET_RASTER_RESOLUTION_Y, + HANDLE_VIEWSET_RASTER_SUBDIVISION_X, + HANDLE_VIEWSET_RASTER_SUBDIVISION_Y, + HANDLE_VIEWSET_HORI_RULER_METRIC, + HANDLE_VIEWSET_VERT_RULER_METRIC, + HANDLE_VIEWSET_SCROLLBAR_TIPS, + HANDLE_VIEWSET_INLINECHANGES_TIPS, + HANDLE_VIEWSET_HIDE_WHITESPACE, + HANDLE_VIEWSET_USE_HEADERFOOTERMENU, + HANDLE_VIEWSET_BOOKMARKS, + HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON, + HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT, + HANDLE_VIEWSET_CHANGES_IN_MARGIN +}; + +enum SwPrintSettingsPropertyHandles +{ + HANDLE_PRINTSET_ANNOTATION_MODE, + HANDLE_PRINTSET_BLACK_FONTS, + HANDLE_PRINTSET_CONTROLS, + HANDLE_PRINTSET_DRAWINGS, + HANDLE_PRINTSET_GRAPHICS, + HANDLE_PRINTSET_LEFT_PAGES, + HANDLE_PRINTSET_PAGE_BACKGROUND, + HANDLE_PRINTSET_PROSPECT, + HANDLE_PRINTSET_REVERSED, + HANDLE_PRINTSET_RIGHT_PAGES, + HANDLE_PRINTSET_FAX_NAME, + HANDLE_PRINTSET_PAPER_FROM_SETUP, + HANDLE_PRINTSET_TABLES, + HANDLE_PRINTSET_SINGLE_JOBS, + HANDLE_PRINTSET_EMPTY_PAGES, + HANDLE_PRINTSET_PROSPECT_RTL, + HANDLE_PRINTSET_PLACEHOLDER, + HANDLE_PRINTSET_HIDDEN_TEXT +}; + +} + +static rtl::Reference<ChainablePropertySetInfo> lcl_createViewSettingsInfo() +{ + static PropertyInfo const aViewSettingsMap_Impl[] = + { + { OUString( "HelpURL" ), HANDLE_VIEWSET_HELP_URL , cppu::UnoType<OUString>::get(), PROPERTY_NONE}, + { OUString( "HorizontalRulerMetric"),HANDLE_VIEWSET_HORI_RULER_METRIC , cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "IsRasterVisible"), HANDLE_VIEWSET_IS_RASTER_VISIBLE, cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "IsSnapToRaster"), HANDLE_VIEWSET_IS_SNAP_TO_RASTER, cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "IsVertRulerRightAligned"),HANDLE_VIEWSET_VRULER_RIGHT , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowContentTips" ), HANDLE_VIEWSET_SHOW_CONTENT_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowInlineTooltips" ), HANDLE_VIEWSET_INLINECHANGES_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "UseHeaderFooterMenu" ), HANDLE_VIEWSET_USE_HEADERFOOTERMENU , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowOutlineContentVisibilityButton" ), HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "TreatSubOutlineLevelsAsContent" ), HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowChangesInMargin" ), HANDLE_VIEWSET_CHANGES_IN_MARGIN, cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "RasterResolutionX"), HANDLE_VIEWSET_RASTER_RESOLUTION_X, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "RasterResolutionY"), HANDLE_VIEWSET_RASTER_RESOLUTION_Y, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "RasterSubdivisionX"), HANDLE_VIEWSET_RASTER_SUBDIVISION_X, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "RasterSubdivisionY"), HANDLE_VIEWSET_RASTER_SUBDIVISION_Y, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "ShowAnnotations" ), HANDLE_VIEWSET_ANNOTATIONS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowBookmarks" ), HANDLE_VIEWSET_BOOKMARKS, cppu::UnoType<bool>::get(), PROPERTY_NONE }, + { OUString( "ShowBreaks"), HANDLE_VIEWSET_BREAKS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowDrawings"), HANDLE_VIEWSET_DRAWINGS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowFieldCommands"), HANDLE_VIEWSET_FIELD_COMMANDS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowFootnoteBackground"),HANDLE_VIEWSET_FOOTNOTE_BACKGROUND , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowGraphics"), HANDLE_VIEWSET_GRAPHICS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenCharacters"), HANDLE_VIEWSET_HIDDEN_CHARACTERS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "HideWhitespace"), HANDLE_VIEWSET_HIDE_WHITESPACE , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenParagraphs"), HANDLE_VIEWSET_HIDDEN_PARAGRAPHS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowHiddenText"), HANDLE_VIEWSET_HIDDEN_TEXT , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowHoriRuler"), HANDLE_VIEWSET_HRULER , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowHoriScrollBar"), HANDLE_VIEWSET_HSCROLL , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowIndexMarkBackground"),HANDLE_VIEWSET_INDEX_MARK_BACKGROUND, cppu::UnoType<bool>::get(),PROPERTY_NONE}, + { OUString( "ShowNonprintingCharacters"),HANDLE_VIEWSET_NONPRINTING_CHARACTERS, cppu::UnoType<bool>::get(),PROPERTY_NONE}, + { OUString( "ShowOnlineLayout"), HANDLE_VIEWSET_ONLINE_LAYOUT , cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID}, + { OUString( "ShowParaBreaks"), HANDLE_VIEWSET_PARA_BREAKS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowProtectedSpaces"), HANDLE_VIEWSET_PROTECTED_SPACES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowRulers"), HANDLE_VIEWSET_SHOW_RULER , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowScrollBarTips"), HANDLE_VIEWSET_SCROLLBAR_TIPS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowSoftHyphens"), HANDLE_VIEWSET_SOFT_HYPHENS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowSpaces"), HANDLE_VIEWSET_SPACES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowTableBoundaries"), HANDLE_VIEWSET_TABLE_BOUNDARIES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowTables"), HANDLE_VIEWSET_TABLES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowTabstops"), HANDLE_VIEWSET_TABSTOPS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowTextBoundaries"), HANDLE_VIEWSET_TEXT_BOUNDARIES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowTextFieldBackground"),HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND, cppu::UnoType<bool>::get(),PROPERTY_NONE}, + { OUString( "ShowVertRuler"), HANDLE_VIEWSET_VRULER , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "ShowVertScrollBar"), HANDLE_VIEWSET_VSCROLL , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "SmoothScrolling"), HANDLE_VIEWSET_SMOOTH_SCROLLING , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "VerticalRulerMetric"), HANDLE_VIEWSET_VERT_RULER_METRIC , cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE}, + { OUString( "ZoomType"), HANDLE_VIEWSET_ZOOM_TYPE , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE}, + { OUString( "ZoomValue"), HANDLE_VIEWSET_ZOOM , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE}, + { OUString(), 0, css::uno::Type(), 0 } + }; + return new ChainablePropertySetInfo ( aViewSettingsMap_Impl ); +} + +static rtl::Reference<ChainablePropertySetInfo> lcl_createPrintSettingsInfo() +{ + static PropertyInfo const aPrintSettingsMap_Impl[] = + { + { OUString( "PrintAnnotationMode" ), HANDLE_PRINTSET_ANNOTATION_MODE , cppu::UnoType<sal_Int16>::get(), PROPERTY_NONE}, + { OUString( "PrintBlackFonts" ), HANDLE_PRINTSET_BLACK_FONTS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintControls" ), HANDLE_PRINTSET_CONTROLS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintDrawings" ), HANDLE_PRINTSET_DRAWINGS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintGraphics" ), HANDLE_PRINTSET_GRAPHICS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintHiddenText"), HANDLE_PRINTSET_HIDDEN_TEXT , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintLeftPages" ), HANDLE_PRINTSET_LEFT_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintPageBackground" ), HANDLE_PRINTSET_PAGE_BACKGROUND , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintProspect" ), HANDLE_PRINTSET_PROSPECT , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintProspectRTL" ), HANDLE_PRINTSET_PROSPECT_RTL , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintReversed" ), HANDLE_PRINTSET_REVERSED , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintRightPages" ), HANDLE_PRINTSET_RIGHT_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintFaxName" ), HANDLE_PRINTSET_FAX_NAME , cppu::UnoType<OUString>::get(), PROPERTY_NONE}, + { OUString( "PrintPaperFromSetup" ), HANDLE_PRINTSET_PAPER_FROM_SETUP , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintTables" ), HANDLE_PRINTSET_TABLES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintTextPlaceholder"), HANDLE_PRINTSET_PLACEHOLDER , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintSingleJobs" ), HANDLE_PRINTSET_SINGLE_JOBS , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString( "PrintEmptyPages" ), HANDLE_PRINTSET_EMPTY_PAGES , cppu::UnoType<bool>::get(), PROPERTY_NONE}, + { OUString(), 0, css::uno::Type(), 0} + }; + return new ChainablePropertySetInfo ( aPrintSettingsMap_Impl ); +} + +SwXModule::SwXModule() +{ +} + +SwXModule::~SwXModule() +{ +} + +Reference< XPropertySet > SwXModule::getViewSettings() +{ + SolarMutexGuard aGuard; + if(!mxViewSettings.is()) + { + OSL_FAIL("Web or Text?"); + mxViewSettings = new SwXViewSettings( nullptr ); + } + return mxViewSettings; +} + +Reference< XPropertySet > SwXModule::getPrintSettings() +{ + SolarMutexGuard aGuard; + if(!mxPrintSettings.is()) + { + OSL_FAIL("Web or Text?"); + mxPrintSettings = new SwXPrintSettings( SwXPrintSettingsType::Module ); + } + return mxPrintSettings; +} + +OUString SwXModule::getImplementationName() +{ + return "SwXModule"; +} + +sal_Bool SwXModule::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXModule::getSupportedServiceNames() +{ + return { "com.sun.star.text.GlobalSettings" }; +} + +SwXPrintSettings::SwXPrintSettings(SwXPrintSettingsType eType, SwDoc* pDoc) +: ChainablePropertySet ( lcl_createPrintSettingsInfo().get(), &Application::GetSolarMutex() ) +, meType(eType) +, mpPrtOpt ( nullptr ) +, mpDoc ( pDoc ) +{ +} + +SwXPrintSettings::~SwXPrintSettings() + noexcept +{ +} + +void SwXPrintSettings::_preSetValues () +{ + switch (meType) + { + case SwXPrintSettingsType::Module: + mpPrtOpt = SW_MOD()->GetPrtOptions( false ); + break; + case SwXPrintSettingsType::Document: + { + if (!mpDoc) + throw IllegalArgumentException (); + mpPrtOpt = const_cast< SwPrintData * >(&mpDoc->getIDocumentDeviceAccess().getPrintData()); + } + break; + } +} + +namespace +{ + bool tryBoolAccess(std::u16string_view rName, const uno::Any &rValue) + { + const std::optional<const bool> xPrSet = o3tl::tryAccess<bool>(rValue); + if (!xPrSet.has_value()) + throw lang::IllegalArgumentException(OUString(OUString::Concat(rName) + " no value"), nullptr, 0); + return *xPrSet; + } +} + +void SwXPrintSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue ) +{ + switch( rInfo.mnHandle ) + { + case HANDLE_PRINTSET_LEFT_PAGES: + { + mpPrtOpt->SetPrintLeftPage(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_RIGHT_PAGES: + { + mpPrtOpt->SetPrintRightPage(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_REVERSED: + { + mpPrtOpt->SetPrintReverse(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_PROSPECT: + { + mpPrtOpt->SetPrintProspect(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_GRAPHICS: + { + mpPrtOpt->SetPrintGraphic(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_TABLES: + { + mpPrtOpt->SetPrintTable(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_DRAWINGS: + { + mpPrtOpt->SetPrintDraw(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_CONTROLS: + { + mpPrtOpt->SetPrintControl(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_PAGE_BACKGROUND: + { + mpPrtOpt->SetPrintPageBackground(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_BLACK_FONTS: + { + mpPrtOpt->SetPrintBlackFont(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_SINGLE_JOBS: + { + mpPrtOpt->SetPrintSingleJobs(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_PAPER_FROM_SETUP: + { + mpPrtOpt->SetPaperFromSetup(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_ANNOTATION_MODE: + { + sal_Int16 nTmp = 0; + rValue >>= nTmp; + SwPostItMode nVal = static_cast<SwPostItMode>(nTmp); + if(nVal > SwPostItMode::EndPage) + throw lang::IllegalArgumentException(OUString::number(nTmp) + " > SwPostItMode::EndPage", nullptr, 0); + + mpPrtOpt->SetPrintPostIts(nVal); + } + break; + case HANDLE_PRINTSET_EMPTY_PAGES: + { + mpPrtOpt->SetPrintEmptyPages(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_FAX_NAME: + { + OUString sString; + if ( !(rValue >>= sString)) + throw lang::IllegalArgumentException(); + + mpPrtOpt->SetFaxName(sString); + } + break; + case HANDLE_PRINTSET_PROSPECT_RTL: + { + mpPrtOpt->SetPrintProspect_RTL(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_PLACEHOLDER: + { + mpPrtOpt->SetPrintTextPlaceholder(tryBoolAccess(rInfo.maName, rValue)); + } + break; + case HANDLE_PRINTSET_HIDDEN_TEXT: + { + mpPrtOpt->SetPrintHiddenText(tryBoolAccess(rInfo.maName, rValue)); + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXPrintSettings::_postSetValues() +{ + mpPrtOpt = nullptr; +} + +void SwXPrintSettings::_preGetValues() +{ + switch (meType) + { + case SwXPrintSettingsType::Module: + mpPrtOpt = SW_MOD()->GetPrtOptions( false ); + break; + case SwXPrintSettingsType::Document: + { + if (!mpDoc) + throw IllegalArgumentException (); + mpPrtOpt = const_cast< SwPrintData * >(&mpDoc->getIDocumentDeviceAccess().getPrintData()); + } + break; + } +} + +void SwXPrintSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue ) +{ + switch( rInfo.mnHandle ) + { + case HANDLE_PRINTSET_LEFT_PAGES: + rValue <<= mpPrtOpt->IsPrintLeftPage(); + break; + case HANDLE_PRINTSET_RIGHT_PAGES: + rValue <<= mpPrtOpt->IsPrintRightPage(); + break; + case HANDLE_PRINTSET_REVERSED: + rValue <<= mpPrtOpt->IsPrintReverse(); + break; + case HANDLE_PRINTSET_PROSPECT: + rValue <<= mpPrtOpt->IsPrintProspect(); + break; + case HANDLE_PRINTSET_GRAPHICS: + rValue <<= mpPrtOpt->IsPrintGraphic(); + break; + case HANDLE_PRINTSET_TABLES: + rValue <<= mpPrtOpt->IsPrintTable(); + break; + case HANDLE_PRINTSET_DRAWINGS: + rValue <<= mpPrtOpt->IsPrintDraw(); + break; + case HANDLE_PRINTSET_CONTROLS: + rValue <<= mpPrtOpt->IsPrintControl(); + break; + case HANDLE_PRINTSET_PAGE_BACKGROUND: + rValue <<= mpPrtOpt->IsPrintPageBackground(); + break; + case HANDLE_PRINTSET_BLACK_FONTS: + rValue <<= mpPrtOpt->IsPrintBlackFont(); + break; + case HANDLE_PRINTSET_SINGLE_JOBS: + rValue <<= mpPrtOpt->IsPrintSingleJobs(); + break; + case HANDLE_PRINTSET_EMPTY_PAGES: + rValue <<= mpPrtOpt->IsPrintEmptyPages(); + break; + case HANDLE_PRINTSET_PAPER_FROM_SETUP: + rValue <<= mpPrtOpt->IsPaperFromSetup(); + break; + case HANDLE_PRINTSET_ANNOTATION_MODE: + { + rValue <<= static_cast < sal_Int16 > ( mpPrtOpt->GetPrintPostIts() ); + } + break; + case HANDLE_PRINTSET_FAX_NAME : + { + rValue <<= mpPrtOpt->GetFaxName(); + } + break; + case HANDLE_PRINTSET_PROSPECT_RTL: + { + rValue <<= mpPrtOpt->IsPrintProspectRTL(); + } + break; + case HANDLE_PRINTSET_PLACEHOLDER: + { + rValue <<= mpPrtOpt->IsPrintTextPlaceholder(); + } + break; + case HANDLE_PRINTSET_HIDDEN_TEXT: + { + rValue <<= mpPrtOpt->IsPrintHiddenText(); + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXPrintSettings::_postGetValues () +{ + mpPrtOpt = nullptr; +} + +OUString SwXPrintSettings::getImplementationName() +{ + return "SwXPrintSettings"; +} + +sal_Bool SwXPrintSettings::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXPrintSettings::getSupportedServiceNames() +{ + Sequence<OUString> aRet { "com.sun.star.text.PrintSettings" }; + return aRet; +} + +SwXViewSettings::SwXViewSettings(SwView* pVw) + : ChainablePropertySet( lcl_createViewSettingsInfo().get(), &Application::GetSolarMutex() ) + , m_pView(pVw) + , mpConstViewOption(nullptr) + , m_bObjectValid(true) + , mbApplyZoom(false) + , m_eHRulerUnit(FieldUnit::CM) + , mbApplyHRulerMetric(false) + , m_eVRulerUnit(FieldUnit::CM) + , mbApplyVRulerMetric(false) +{ + // This property only exists if we have a view (ie, not at the module ) + if ( !m_pView ) + mxInfo->remove ( "HelpURL" ); + +} + +SwXViewSettings::~SwXViewSettings() + noexcept +{ + +} + +void SwXViewSettings::_preSetValues () +{ + const SwViewOption* pVOpt = nullptr; + if(m_pView) + { + if(!IsValid()) + return; + pVOpt = m_pView->GetWrtShell().GetViewOptions(); + } + else + pVOpt = SW_MOD()->GetViewOption(false); + + mpViewOption.reset( new SwViewOption (*pVOpt) ); + mbApplyZoom = false; + if(m_pView) + mpViewOption->SetStarOneSetting(true); +} + +void SwXViewSettings::_setSingleValue( const comphelper::PropertyInfo & rInfo, const uno::Any &rValue ) +{ + // the API flag should not be set to the application's view settings + switch( rInfo.mnHandle ) + { + case HANDLE_VIEWSET_SHOW_RULER : mpViewOption->SetViewAnyRuler(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_HRULER : mpViewOption->SetViewHRuler(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_VRULER : mpViewOption->SetViewVRuler(*o3tl::doAccess<bool>(rValue));break; + case HANDLE_VIEWSET_VRULER_RIGHT : mpViewOption->SetVRulerRight(*o3tl::doAccess<bool>(rValue));break; + case HANDLE_VIEWSET_HSCROLL : mpViewOption->SetViewHScrollBar(*o3tl::doAccess<bool>(rValue));break; + case HANDLE_VIEWSET_VSCROLL : mpViewOption->SetViewVScrollBar(*o3tl::doAccess<bool>(rValue));break; + case HANDLE_VIEWSET_GRAPHICS : mpViewOption->SetGraphic(*o3tl::doAccess<bool>(rValue));break; + case HANDLE_VIEWSET_TABLES : mpViewOption->SetTable(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_DRAWINGS : mpViewOption->SetDraw(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_FIELD_COMMANDS : mpViewOption->SetFieldName(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_ANNOTATIONS : mpViewOption->SetPostIts(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_INDEX_MARK_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break; + case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: mpViewOption->SetViewMetaChars( *o3tl::doAccess<bool>(rValue) ); break; + case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break; + case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : mpViewOption->SetAppearanceFlag(ViewOptFlags::FieldShadings, *o3tl::doAccess<bool>(rValue), true); break; + case HANDLE_VIEWSET_PARA_BREAKS : mpViewOption->SetParagraph(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SOFT_HYPHENS : mpViewOption->SetSoftHyph(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SPACES : mpViewOption->SetBlank(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_PROTECTED_SPACES : mpViewOption->SetHardBlank(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_TABSTOPS : mpViewOption->SetTab(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_BREAKS : mpViewOption->SetLineBreak(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_BOOKMARKS : mpViewOption->SetShowBookmarks(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_TEXT : mpViewOption->SetShowHiddenField(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_CHARACTERS : mpViewOption->SetShowHiddenChar(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_HIDDEN_PARAGRAPHS : mpViewOption->SetShowHiddenPara(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_TABLE_BOUNDARIES : mpViewOption->SetAppearanceFlag(ViewOptFlags::TableBoundaries, *o3tl::doAccess<bool>(rValue), true); break; + case HANDLE_VIEWSET_TEXT_BOUNDARIES : mpViewOption->SetDocBoundaries(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SMOOTH_SCROLLING : mpViewOption->SetSmoothScroll(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SHOW_CONTENT_TIPS : mpViewOption->SetShowContentTips(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_IS_RASTER_VISIBLE : mpViewOption->SetGridVisible(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_IS_SNAP_TO_RASTER : mpViewOption->SetSnap(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SCROLLBAR_TIPS : mpViewOption->SetShowScrollBarTips(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_INLINECHANGES_TIPS : mpViewOption->SetShowInlineTooltips(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_USE_HEADERFOOTERMENU : mpViewOption->SetUseHeaderFooterMenu(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_SHOW_OUTLINECONTENTVISIBILITYBUTTON : mpViewOption->SetShowOutlineContentVisibilityButton(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_TREAT_SUB_OUTLINE_LEVELS_AS_CONTENT : mpViewOption->SetTreatSubOutlineLevelsAsContent(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_CHANGES_IN_MARGIN : mpViewOption->SetShowChangesInMargin(*o3tl::doAccess<bool>(rValue)); break; + case HANDLE_VIEWSET_RASTER_RESOLUTION_X : + { + sal_Int32 nTmp = 0; + if(!(rValue >>= nTmp) || nTmp < 10) + throw IllegalArgumentException(); + Size aSize( mpViewOption->GetSnapSize() ); + aSize.setWidth( o3tl::toTwips(nTmp, o3tl::Length::mm100) ); + mpViewOption->SetSnapSize( aSize ); + } + break; + case HANDLE_VIEWSET_RASTER_RESOLUTION_Y : + { + sal_Int32 nTmp = 0; + if(!(rValue >>= nTmp) || nTmp < 10) + throw IllegalArgumentException(); + Size aSize( mpViewOption->GetSnapSize() ); + aSize.setHeight( o3tl::toTwips(nTmp, o3tl::Length::mm100) ); + mpViewOption->SetSnapSize( aSize ); + } + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_X : + { + sal_Int32 nTmp = 0; + if(!(rValue >>= nTmp) || (0 > nTmp || nTmp >= 100)) + throw IllegalArgumentException(); + mpViewOption->SetDivisionX( static_cast<short>(nTmp) ); + } + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_Y : + { + sal_Int32 nTmp = 0; + if(!(rValue >>= nTmp) || (0 > nTmp || nTmp >= 100)) + throw IllegalArgumentException(); + mpViewOption->SetDivisionY( static_cast<short>(nTmp) ); + } + break; + case HANDLE_VIEWSET_ZOOM : + { + sal_Int16 nZoom = 0; + if(!(rValue >>= nZoom) || nZoom > MAXZOOM || nZoom < MINZOOM) + throw lang::IllegalArgumentException(); + mpViewOption->SetZoom(o3tl::narrowing<sal_uInt16>(nZoom)); + mbApplyZoom = true; + } + break; + case HANDLE_VIEWSET_ZOOM_TYPE: + { + sal_Int16 nZoom = 0; + if(!(rValue >>= nZoom)) + throw IllegalArgumentException(); + SvxZoomType eZoom; + switch (nZoom) + { + case view::DocumentZoomType::OPTIMAL: + eZoom = SvxZoomType::OPTIMAL; + break; + case view::DocumentZoomType::PAGE_WIDTH: + eZoom = SvxZoomType::PAGEWIDTH; + break; + case view::DocumentZoomType::ENTIRE_PAGE: + eZoom = SvxZoomType::WHOLEPAGE; + break; + case view::DocumentZoomType::BY_VALUE: + eZoom = SvxZoomType::PERCENT; + break; + case view::DocumentZoomType::PAGE_WIDTH_EXACT: + eZoom = SvxZoomType::PAGEWIDTH_NOBORDER; + break; + default: + throw IllegalArgumentException( + "SwXViewSettings: invalid zoom type", nullptr, 0); + } + mpViewOption->SetZoomType( eZoom ); + mbApplyZoom = true; + } + break; + case HANDLE_VIEWSET_ONLINE_LAYOUT : + { + if ( m_pView ) + { + bool bVal = *o3tl::doAccess<bool>(rValue); + SwViewOption aOpt(*m_pView->GetWrtShell().GetViewOptions()); + if (!bVal != !aOpt.getBrowseMode()) + { + aOpt.setBrowseMode( bVal ); + m_pView->GetWrtShell().ApplyViewOptions( aOpt ); + + // must be set in mpViewOption as this will overwrite settings in _post! + if(mpViewOption) + mpViewOption->setBrowseMode(bVal); + + m_pView->GetDocShell()->ToggleLayoutMode(m_pView); + } + } + } + break; + case HANDLE_VIEWSET_HIDE_WHITESPACE: + { + if ( m_pView ) + { + bool bVal = *o3tl::doAccess<bool>(rValue); + SwViewOption aOpt(*m_pView->GetWrtShell().GetViewOptions()); + if (!bVal != !aOpt.IsHideWhitespaceMode()) + { + aOpt.SetHideWhitespaceMode( bVal ); + m_pView->GetWrtShell().ApplyViewOptions( aOpt ); + + // must be set in mpViewOption as this will overwrite settings in _post! + if(mpViewOption) + mpViewOption->SetHideWhitespaceMode(bVal); + } + } + } + break; + case HANDLE_VIEWSET_HELP_URL: + { + if ( !m_pView ) + throw UnknownPropertyException(); + + OUString sHelpURL; + if ( ! ( rValue >>= sHelpURL ) ) + throw IllegalArgumentException(); + + INetURLObject aHID( sHelpURL ); + if ( aHID.GetProtocol() != INetProtocol::Hid ) + throw IllegalArgumentException (); + + m_pView->GetEditWin().SetHelpId( aHID.GetURLPath() ); + } + break; + case HANDLE_VIEWSET_HORI_RULER_METRIC: + case HANDLE_VIEWSET_VERT_RULER_METRIC: + { + sal_uInt16 nUnit; + if( rValue >>= nUnit ) + switch (static_cast<FieldUnit>(nUnit)) + { + case FieldUnit::MM: + case FieldUnit::CM: + case FieldUnit::POINT: + case FieldUnit::PICA: + case FieldUnit::INCH: + if( rInfo.mnHandle == HANDLE_VIEWSET_HORI_RULER_METRIC ) + { + m_eHRulerUnit = static_cast<FieldUnit>(nUnit); + mbApplyHRulerMetric = true; + } + else + { + m_eVRulerUnit = static_cast<FieldUnit>(nUnit); + mbApplyVRulerMetric = true; + } + break; + default: + throw IllegalArgumentException(); + } + } + break; + default: + throw UnknownPropertyException(OUString::number(rInfo.mnHandle)); + } +} + +void SwXViewSettings::_postSetValues() +{ + if( m_pView ) + { + if(mbApplyZoom ) + m_pView->SetZoom( mpViewOption->GetZoomType(), + mpViewOption->GetZoom(), true ); + if(mbApplyHRulerMetric) + m_pView->ChangeTabMetric(m_eHRulerUnit); + if(mbApplyVRulerMetric) + m_pView->ChangeVRulerMetric(m_eVRulerUnit); + + } + else + { + if(mbApplyHRulerMetric) + SW_MOD()->ApplyRulerMetric( m_eHRulerUnit, true, false ); + if(mbApplyVRulerMetric) + SW_MOD()->ApplyRulerMetric( m_eVRulerUnit, false, false ); + } + + SW_MOD()->ApplyUsrPref( *mpViewOption, m_pView, m_pView ? SvViewOpt::DestViewOnly + : SvViewOpt::DestText ); + + mpViewOption.reset(); +} + +void SwXViewSettings::_preGetValues () +{ + if(m_pView) + { + if(!IsValid()) + return; + mpConstViewOption = m_pView->GetWrtShell().GetViewOptions(); + } + else + mpConstViewOption = SW_MOD()->GetViewOption(false); +} + +void SwXViewSettings::_getSingleValue( const comphelper::PropertyInfo & rInfo, uno::Any & rValue ) +{ + bool bBool = true; + bool bBoolVal = false; + switch( rInfo.mnHandle ) + { + case HANDLE_VIEWSET_SHOW_RULER: bBoolVal = mpConstViewOption->IsViewAnyRuler(); break; + case HANDLE_VIEWSET_HRULER : bBoolVal = mpConstViewOption->IsViewHRuler(true); break; + case HANDLE_VIEWSET_VRULER : bBoolVal = mpConstViewOption->IsViewVRuler(true);break; + case HANDLE_VIEWSET_VRULER_RIGHT : bBoolVal = mpConstViewOption->IsVRulerRight();break; + case HANDLE_VIEWSET_HSCROLL: bBoolVal = mpConstViewOption->IsViewHScrollBar();break; + case HANDLE_VIEWSET_VSCROLL: bBoolVal = mpConstViewOption->IsViewVScrollBar();break; + case HANDLE_VIEWSET_GRAPHICS : bBoolVal = mpConstViewOption->IsGraphic();break; + case HANDLE_VIEWSET_TABLES : bBoolVal = mpConstViewOption->IsTable(); break; + case HANDLE_VIEWSET_DRAWINGS : bBoolVal = mpConstViewOption->IsDraw(); break; + case HANDLE_VIEWSET_FIELD_COMMANDS : bBoolVal = mpConstViewOption->IsFieldName(); break; + case HANDLE_VIEWSET_ANNOTATIONS : bBoolVal = mpConstViewOption->IsPostIts(); break; + case HANDLE_VIEWSET_INDEX_MARK_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break; + case HANDLE_VIEWSET_NONPRINTING_CHARACTERS: bBoolVal = mpConstViewOption->IsViewMetaChars(); break; + case HANDLE_VIEWSET_FOOTNOTE_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break; + case HANDLE_VIEWSET_TEXT_FIELD_BACKGROUND : bBoolVal = mpConstViewOption->IsFieldShadings(); break; + case HANDLE_VIEWSET_PARA_BREAKS : bBoolVal = mpConstViewOption->IsParagraph(true); break; + case HANDLE_VIEWSET_SOFT_HYPHENS : bBoolVal = mpConstViewOption->IsSoftHyph(); break; + case HANDLE_VIEWSET_SPACES : bBoolVal = mpConstViewOption->IsBlank(true); break; + case HANDLE_VIEWSET_PROTECTED_SPACES : bBoolVal = mpConstViewOption->IsHardBlank(); break; + case HANDLE_VIEWSET_TABSTOPS : bBoolVal = mpConstViewOption->IsTab(true); break; + case HANDLE_VIEWSET_BREAKS : bBoolVal = mpConstViewOption->IsLineBreak(true); break; + case HANDLE_VIEWSET_BOOKMARKS : bBoolVal = mpConstViewOption->IsShowBookmarks(true); break; + case HANDLE_VIEWSET_HIDDEN_TEXT : bBoolVal = mpConstViewOption->IsShowHiddenField(); break; + case HANDLE_VIEWSET_HIDDEN_CHARACTERS : bBoolVal = mpConstViewOption->IsShowHiddenChar(true); break; + case HANDLE_VIEWSET_HIDE_WHITESPACE : bBoolVal = mpConstViewOption->IsHideWhitespaceMode(); break; + case HANDLE_VIEWSET_HIDDEN_PARAGRAPHS : bBoolVal = mpConstViewOption->IsShowHiddenPara(); break; + case HANDLE_VIEWSET_TABLE_BOUNDARIES : bBoolVal = mpConstViewOption->IsTableBoundaries(); break; + case HANDLE_VIEWSET_TEXT_BOUNDARIES : bBoolVal = mpConstViewOption->IsDocBoundaries(); break; + case HANDLE_VIEWSET_SMOOTH_SCROLLING : bBoolVal = mpConstViewOption->IsSmoothScroll(); break; + case HANDLE_VIEWSET_SHOW_CONTENT_TIPS : bBoolVal = mpConstViewOption->IsShowContentTips(); break; + case HANDLE_VIEWSET_INLINECHANGES_TIPS : bBoolVal = mpConstViewOption->IsShowInlineTooltips(); break; + case HANDLE_VIEWSET_CHANGES_IN_MARGIN : bBoolVal = mpConstViewOption->IsShowChangesInMargin(); break; + case HANDLE_VIEWSET_IS_RASTER_VISIBLE : bBoolVal = mpConstViewOption->IsGridVisible(); break; + case HANDLE_VIEWSET_IS_SNAP_TO_RASTER : bBoolVal = mpConstViewOption->IsSnap(); break; + case HANDLE_VIEWSET_SCROLLBAR_TIPS : bBoolVal = mpConstViewOption->IsShowScrollBarTips(); break; + case HANDLE_VIEWSET_RASTER_RESOLUTION_X : + bBool = false; + rValue <<= static_cast<sal_Int32>(convertTwipToMm100(mpConstViewOption->GetSnapSize().Width())); + break; + case HANDLE_VIEWSET_RASTER_RESOLUTION_Y : + bBool = false; + rValue <<= static_cast<sal_Int32>(convertTwipToMm100(mpConstViewOption->GetSnapSize().Height())); + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_X : + bBool = false; + rValue <<= static_cast<sal_Int32>(mpConstViewOption->GetDivisionX()); + break; + case HANDLE_VIEWSET_RASTER_SUBDIVISION_Y : + bBool = false; + rValue <<= static_cast<sal_Int32>(mpConstViewOption->GetDivisionY()); + break; + case HANDLE_VIEWSET_ZOOM : + bBool = false; + rValue <<= static_cast<sal_Int16>(mpConstViewOption->GetZoom()); + break; + case HANDLE_VIEWSET_ZOOM_TYPE: + { + bBool = false; + sal_Int16 nRet(0); + switch (mpConstViewOption->GetZoomType()) + { + case SvxZoomType::OPTIMAL: + nRet = view::DocumentZoomType::OPTIMAL; + break; + case SvxZoomType::PAGEWIDTH: + nRet = view::DocumentZoomType::PAGE_WIDTH; + break; + case SvxZoomType::WHOLEPAGE: + nRet = view::DocumentZoomType::ENTIRE_PAGE; + break; + case SvxZoomType::PERCENT: + nRet = view::DocumentZoomType::BY_VALUE; + break; + case SvxZoomType::PAGEWIDTH_NOBORDER: + nRet = view::DocumentZoomType::PAGE_WIDTH_EXACT; + break; + default: + OSL_FAIL("SwXViewSettings: invalid zoom type"); + break; + } + rValue <<= nRet; + } + break; + case HANDLE_VIEWSET_ONLINE_LAYOUT: + if(m_pView) + bBoolVal = m_pView->GetWrtShell().GetViewOptions()->getBrowseMode(); + break; + case HANDLE_VIEWSET_HELP_URL : + { + if ( !m_pView ) + throw UnknownPropertyException(); + + bBool = false; + SwEditWin &rEditWin = m_pView->GetEditWin(); + OUString sHelpURL = INET_HID_SCHEME + rEditWin.GetHelpId(); + rValue <<= sHelpURL; + } + break; + case HANDLE_VIEWSET_HORI_RULER_METRIC: + { + if ( m_pView ) + { + FieldUnit eUnit; + m_pView->GetHRulerMetric( eUnit ); + rValue <<= static_cast<sal_Int32>(eUnit); + } + else + { + const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false ); + rValue <<= static_cast<sal_Int32>(pUsrPref->GetHScrollMetric()); + } + bBool = false; + } + break; + case HANDLE_VIEWSET_VERT_RULER_METRIC: + { + if ( m_pView ) + { + FieldUnit eUnit; + m_pView->GetVRulerMetric( eUnit ); + rValue <<= static_cast<sal_Int32>(eUnit); + } + else + { + const SwMasterUsrPref* pUsrPref = SW_MOD()->GetUsrPref( false ); + rValue <<= static_cast<sal_Int32>(pUsrPref->GetVScrollMetric()); + } + bBool = false; + } + break; + default: OSL_FAIL("there is no such ID!"); + } + if( bBool ) + rValue <<= bBoolVal; +} + +void SwXViewSettings::_postGetValues () +{ + mpConstViewOption = nullptr; +} + +OUString SwXViewSettings::getImplementationName() +{ + return "SwXViewSettings"; +} + +sal_Bool SwXViewSettings::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXViewSettings::getSupportedServiceNames() +{ + Sequence<OUString> aRet { "com.sun.star.text.ViewSettings" }; + return aRet; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +SwXModule_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SwXModule()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unomodule.cxx b/sw/source/uibase/uno/unomodule.cxx new file mode 100644 index 0000000000..478502c4fe --- /dev/null +++ b/sw/source/uibase/uno/unomodule.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/frame/DispatchResultState.hpp> +#include <com/sun/star/frame/Desktop.hpp> + +#include <swmodule.hxx> +#include <swdll.hxx> +#include "unomodule.hxx" +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/frame.hxx> +#include <vcl/svapp.hxx> + +using namespace css; + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_Writer_WriterModule_get_implementation(uno::XComponentContext* /*pCtx*/, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + SolarMutexGuard aGuard; + return cppu::acquire(new SwUnoModule); +} + + // XNotifyingDispatch +void SAL_CALL SwUnoModule::dispatchWithNotification( const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs, const uno::Reference< frame::XDispatchResultListener >& xListener ) +{ + // there is no guarantee, that we are holded alive during this method! + // May the outside dispatch container will be updated by a CONTEXT_CHANGED + // asynchronous ... + uno::Reference< uno::XInterface > xThis(static_cast< frame::XNotifyingDispatch* >(this)); + + SolarMutexGuard aGuard; + SwGlobals::ensure(); + const SfxSlot* pSlot = SW_MOD()->GetInterface()->GetSlot( aURL.Complete ); + + sal_Int16 aState = frame::DispatchResultState::DONTKNOW; + if ( !pSlot ) + aState = frame::DispatchResultState::FAILURE; + else + { + SfxRequest aReq( pSlot, aArgs, SfxCallMode::SYNCHRON, SW_MOD()->GetPool() ); + SfxAllItemSet aInternalSet( SfxGetpApp()->GetPool() ); + + css::uno::Reference<css::frame::XDesktop2> xDesktop = css::frame::Desktop::create(::comphelper::getProcessComponentContext()); + css::uno::Reference<css::frame::XFrame> xCurrentFrame = xDesktop->getCurrentFrame(); + if (xCurrentFrame.is()) // an empty set is no problem ... but an empty frame reference can be a problem ! + aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, xCurrentFrame)); + + aReq.SetInternalArgs_Impl(aInternalSet); + const SfxPoolItemHolder& rResult(SW_MOD()->ExecuteSlot(aReq)); + if (nullptr != rResult.getItem()) + aState = frame::DispatchResultState::SUCCESS; + else + aState = frame::DispatchResultState::FAILURE; + } + + if ( xListener.is() ) + { + xListener->dispatchFinished( + frame::DispatchResultEvent( + xThis, aState, uno::Any())); + } +} + + // XDispatch +void SAL_CALL SwUnoModule::dispatch( const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs ) +{ + dispatchWithNotification(aURL, aArgs, uno::Reference< frame::XDispatchResultListener >()); +} + +void SAL_CALL SwUnoModule::addStatusListener( + const uno::Reference< frame::XStatusListener > & /*xControl*/, + const util::URL& /*aURL*/) +{ +} + +void SAL_CALL SwUnoModule::removeStatusListener( + const uno::Reference< frame::XStatusListener > & /*xControl*/, + const util::URL& /*aURL*/) +{ +} + +uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL SwUnoModule::queryDispatches( + const uno::Sequence< frame::DispatchDescriptor >& seqDescripts ) +{ + sal_Int32 nCount = seqDescripts.getLength(); + uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount ); + + std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.getArray(), + [this](const frame::DispatchDescriptor& rDescr) -> uno::Reference< frame::XDispatch > { + return queryDispatch( rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags ); }); + + return lDispatcher; +} + +// XDispatchProvider +uno::Reference< frame::XDispatch > SAL_CALL SwUnoModule::queryDispatch( + const util::URL& aURL, const OUString& /*sTargetFrameName*/, + sal_Int32 /*eSearchFlags*/ ) +{ + uno::Reference< frame::XDispatch > xReturn; + + SolarMutexGuard aGuard; + SwGlobals::ensure(); + const SfxSlot* pSlot = SW_MOD()->GetInterface()->GetSlot( aURL.Complete ); + if ( pSlot ) + xReturn = this; + + return xReturn; +} + +// XServiceInfo +OUString SAL_CALL SwUnoModule::getImplementationName( ) +{ + return "com.sun.star.comp.Writer.WriterModule"; +} + +sal_Bool SAL_CALL SwUnoModule::supportsService( const OUString& sServiceName ) +{ + return cppu::supportsService(this, sServiceName); +} + +uno::Sequence< OUString > SAL_CALL SwUnoModule::getSupportedServiceNames( ) +{ + uno::Sequence<OUString> aSeq { "com.sun.star.text.ModuleDispatcher" }; + return aSeq; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unomodule.hxx b/sw/source/uibase/uno/unomodule.hxx new file mode 100644 index 0000000000..fa85f11d74 --- /dev/null +++ b/sw/source/uibase/uno/unomodule.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <rtl/ustring.hxx> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XNotifyingDispatch.hpp> +#include <com/sun/star/frame/DispatchDescriptor.hpp> +#include <com/sun/star/uno/Reference.h> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> + +namespace com +{ + namespace sun + { + namespace star + { + namespace lang + { + class XMultiServiceFactory; + } + namespace beans + { + struct PropertyValue; + } + } + } +} + +class SwUnoModule : public ::cppu::WeakImplHelper< css::frame::XDispatchProvider, css::frame::XNotifyingDispatch, css::lang::XServiceInfo > +{ +public: + SwUnoModule() {} + + // XNotifyingDispatch + virtual void SAL_CALL dispatchWithNotification( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs, const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) override; + + // XDispatch + virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& aArgs ) override; + virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override; + virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > & xControl, const css::util::URL& aURL) override; + + // XDispatchProvider + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& seqDescriptor ) override ; + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL & aURL , + const OUString & sTargetFrameName, + sal_Int32 eSearchFlags ) override ; + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx new file mode 100644 index 0000000000..f5e0904fa8 --- /dev/null +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -0,0 +1,4816 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <officecfg/Office/Common.hxx> +#include <comphelper/string.hxx> +#include <AnnotationWin.hxx> +#include <o3tl/any.hxx> +#include <utility> +#include <vcl/virdev.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/svapp.hxx> +#include <vcl/print.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/lokhelper.hxx> +#include <sfx2/LokControlHandler.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/printer.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <toolkit/awt/vclxdevice.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <sfx2/lokcomponenthelpers.hxx> +#include <sfx2/ipclient.hxx> +#include <editeng/svxacorr.hxx> +#include <editeng/acorrcfg.hxx> +#include <cmdid.h> +#include <swtypes.hxx> +#include <wdocsh.hxx> +#include <wrtsh.hxx> +#include <pview.hxx> +#include <viewsh.hxx> +#include <pvprtdat.hxx> +#include <printdata.hxx> +#include <pagefrm.hxx> +#include <rootfrm.hxx> +#include <svl/stritem.hxx> +#include <unotxdoc.hxx> +#include <svl/numformat.hxx> +#include <svl/numuno.hxx> +#include <fldbas.hxx> +#include <unomap.hxx> +#include <unotextbodyhf.hxx> +#include <unotextrange.hxx> +#include <unotextcursor.hxx> +#include <unosett.hxx> +#include <unocoll.hxx> +#include <unoredlines.hxx> +#include <unosrch.hxx> +#include <sfx2/request.hxx> +#include <sfx2/objsh.hxx> +#include <unoprnms.hxx> +#include <unostyle.hxx> +#include <unodraw.hxx> +#include <svl/eitem.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/datetime.hxx> +#include <unocrsr.hxx> +#include <unofieldcoll.hxx> +#include <unoidxcoll.hxx> +#include <unocrsrhelper.hxx> +#include <globdoc.hxx> +#include <viewopt.hxx> +#include <unochart.hxx> +#include <charatr.hxx> +#include <svx/xmleohlp.hxx> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/lang/NotInitializedException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/document/RedlineDisplayType.hpp> +#include <com/sun/star/document/XDocumentEventBroadcaster.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <sfx2/linkmgr.hxx> +#include <svx/unofill.hxx> +#include <swmodule.hxx> +#include <docstat.hxx> +#include <modcfg.hxx> +#include <ndtxt.hxx> +#include <strings.hrc> +#include <bitmaps.hlst> +#include "unodefaults.hxx" +#include "SwXDocumentSettings.hxx" +#include <doc.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentChartDataProviderAccess.hxx> +#include <IDocumentLinksAdministration.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <IDocumentStatistics.hxx> +#include <IDocumentStylePoolAccess.hxx> +#include <IDocumentState.hxx> +#include <drawdoc.hxx> +#include <SwStyleNameMapper.hxx> +#include <osl/file.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/storagehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <sfx2/dispatch.hxx> +#include <swruler.hxx> +#include <docufld.hxx> + +#include <EnhancedPDFExportHelper.hxx> +#include <numrule.hxx> + +#include <editeng/langitem.hxx> +#include <docary.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <i18nutil/searchopt.hxx> + +#include <charfmt.hxx> +#include <fmtcol.hxx> +#include <istyleaccess.hxx> + +#include <swatrset.hxx> +#include <view.hxx> +#include <viscrs.hxx> +#include <srcview.hxx> +#include <edtwin.hxx> +#include <swdtflvr.hxx> +#include <PostItMgr.hxx> + +#include <svtools/langtab.hxx> +#include <map> +#include <set> +#include <vector> + +#include <editeng/eeitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdview.hxx> +#include <comphelper/interfacecontainer4.hxx> +#include <comphelper/servicehelper.hxx> +#include <memory> +#include <redline.hxx> +#include <DocumentRedlineManager.hxx> +#include <xmloff/odffields.hxx> +#include <tools/json_writer.hxx> +#include <tools/UnitConversion.hxx> + +#include <svx/svdpage.hxx> +#include <o3tl/string_view.hxx> +#include <comphelper/sequenceashashmap.hxx> + +#include <IDocumentOutlineNodes.hxx> +#include <SearchResultLocator.hxx> +#include <textcontentcontrol.hxx> +#include <unocontentcontrol.hxx> +#include <unoport.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using ::osl::FileBase; + +static std::unique_ptr<SwPrintUIOptions> lcl_GetPrintUIOptions( + SwDocShell * pDocShell, + const SfxViewShell * pView ) +{ + if (!pDocShell) + return nullptr; + + const bool bWebDoc = nullptr != dynamic_cast< const SwWebDocShell * >(pDocShell); + const bool bSwSrcView = nullptr != dynamic_cast< const SwSrcView * >(pView); + const SwView * pSwView = dynamic_cast< const SwView * >(pView); + const bool bHasSelection = pSwView && pSwView->HasSelection( false ); // check for any selection, not just text selection + const bool bHasPostIts = sw_GetPostIts(pDocShell->GetDoc()->getIDocumentFieldsAccess(), nullptr); + + // get default values to use in dialog from documents SwPrintData + const SwPrintData &rPrintData = pDocShell->GetDoc()->getIDocumentDeviceAccess().getPrintData(); + + // Get current page number + sal_uInt16 nCurrentPage = 1; + const SwWrtShell* pSh = pDocShell->GetWrtShell(); + const SwRootFrame *pFrame = nullptr; + if (pSh) + { + SwPaM* pShellCursor = pSh->GetCursor(); + nCurrentPage = pShellCursor->GetPageNum(); + pFrame = pSh->GetLayout(); + } + else if (!bSwSrcView) + { + const SwPagePreview* pPreview = dynamic_cast< const SwPagePreview* >(pView); + OSL_ENSURE(pPreview, "Unexpected type of the view shell"); + if (pPreview) + { + nCurrentPage = pPreview->GetSelectedPage(); + pFrame = pPreview->GetViewShell()->GetLayout(); + } + } + + // If blanks are skipped, account for them in initial page range value + if (pFrame && !rPrintData.IsPrintEmptyPages()) + { + sal_uInt16 nMax = nCurrentPage; + const SwPageFrame *pPage = dynamic_cast<const SwPageFrame*>(pFrame->Lower()); + while (pPage && nMax-- > 0) + { + if (pPage->getFrameArea().Height() == 0) + nCurrentPage--; + pPage = static_cast<const SwPageFrame*>(pPage->GetNext()); + } + } + return std::make_unique<SwPrintUIOptions>( nCurrentPage, bWebDoc, bSwSrcView, bHasSelection, bHasPostIts, rPrintData ); +} + +static SwTextFormatColl *lcl_GetParaStyle(const OUString& rCollName, SwDoc& rDoc) +{ + SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( rCollName ); + if( !pColl ) + { + const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( + rCollName, SwGetPoolIdFromName::TxtColl ); + if( USHRT_MAX != nId ) + pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( nId ); + } + return pColl; +} + +static void lcl_DisposeView( SfxViewFrame* pToClose, SwDocShell const * pDocShell ) +{ + // check if the view frame still exists + SfxViewFrame* pFound = SfxViewFrame::GetFirst( pDocShell, false ); + while(pFound) + { + if( pFound == pToClose) + { + pToClose->DoClose(); + break; + } + pFound = SfxViewFrame::GetNext( *pFound, pDocShell, false ); + } +} + +class SwXTextDocument::Impl +{ +public: + std::mutex m_Mutex; // just for OInterfaceContainerHelper4 + ::comphelper::OInterfaceContainerHelper4<css::util::XRefreshListener> m_RefreshListeners; +}; + +const Sequence< sal_Int8 > & SwXTextDocument::getUnoTunnelId() +{ + static const comphelper::UnoIdInit theSwXTextDocumentUnoTunnelId; + return theSwXTextDocumentUnoTunnelId.getSeq(); +} + +sal_Int64 SAL_CALL SwXTextDocument::getSomething( const Sequence< sal_Int8 >& rId ) +{ + if( comphelper::isUnoTunnelId<SwXTextDocument>(rId) ) + { + return comphelper::getSomething_cast(this); + } + if( comphelper::isUnoTunnelId<SfxObjectShell>(rId) ) + { + return comphelper::getSomething_cast(m_pDocShell); + } + + sal_Int64 nRet = SfxBaseModel::getSomething( rId ); + if (nRet) + return nRet; + + GetNumberFormatter(); + if (!m_xNumFormatAgg.is()) // may happen if not valid or no SwDoc + return 0; + Any aNumTunnel = m_xNumFormatAgg->queryAggregation(cppu::UnoType<XUnoTunnel>::get()); + Reference<XUnoTunnel> xNumTunnel; + aNumTunnel >>= xNumTunnel; + return (xNumTunnel.is()) ? xNumTunnel->getSomething(rId) : 0; +} + +Any SAL_CALL SwXTextDocument::queryInterface( const uno::Type& rType ) +{ + Any aRet = SwXTextDocumentBaseClass::queryInterface(rType); + if ( !aRet.hasValue() ) + aRet = SfxBaseModel::queryInterface(rType); + if ( !aRet.hasValue() && + rType == cppu::UnoType<lang::XMultiServiceFactory>::get()) + { + Reference<lang::XMultiServiceFactory> xTmp = this; + aRet <<= xTmp; + } + if ( !aRet.hasValue() && + rType == cppu::UnoType<tiledrendering::XTiledRenderable>::get()) + { + Reference<tiledrendering::XTiledRenderable> xTmp = this; + aRet <<= xTmp; + } + + if ( !aRet.hasValue() + && rType != cppu::UnoType<css::document::XDocumentEventBroadcaster>::get() + && rType != cppu::UnoType<css::frame::XController>::get() + && rType != cppu::UnoType<css::frame::XFrame>::get() + && rType != cppu::UnoType<css::script::XInvocation>::get() + && rType != cppu::UnoType<css::beans::XFastPropertySet>::get() + && rType != cppu::UnoType<css::awt::XWindow>::get()) + { + GetNumberFormatter(); + if(m_xNumFormatAgg.is()) + aRet = m_xNumFormatAgg->queryAggregation(rType); + } + return aRet; +} + +void SAL_CALL SwXTextDocument::acquire()noexcept +{ + SfxBaseModel::acquire(); +} + +void SAL_CALL SwXTextDocument::release()noexcept +{ + SfxBaseModel::release(); +} + +Sequence< uno::Type > SAL_CALL SwXTextDocument::getTypes() +{ + Sequence< uno::Type > aNumTypes; + GetNumberFormatter(); + if(m_xNumFormatAgg.is()) + { + const uno::Type& rProvType = cppu::UnoType<XTypeProvider>::get(); + Any aNumProv = m_xNumFormatAgg->queryAggregation(rProvType); + Reference<XTypeProvider> xNumProv; + if(aNumProv >>= xNumProv) + { + aNumTypes = xNumProv->getTypes(); + } + } + return comphelper::concatSequences( + SfxBaseModel::getTypes(), + SwXTextDocumentBaseClass::getTypes(), + aNumTypes, + Sequence { + cppu::UnoType<lang::XMultiServiceFactory>::get(), + cppu::UnoType<tiledrendering::XTiledRenderable>::get()}); +} + +SwXTextDocument::SwXTextDocument(SwDocShell* pShell) + : SwXTextDocumentBaseClass(pShell) + , m_pImpl(new Impl) + , + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_DOCUMENT)), + m_pDocShell(pShell), + m_bObjectValid(pShell != nullptr), + m_pHiddenViewFrame(nullptr), + // #i117783# + m_bApplyPagePrintSettingsFromXPagePrintable( false ) +{ +} + +SwDoc& SwXTextDocument::GetDocOrThrow() const +{ + if (SwDoc* pDoc = m_pDocShell->GetDoc()) + return *pDoc; + throw css::lang::NotInitializedException( + u"Document not initialized by a call to attachResource() or load()"_ustr, + const_cast<SwXTextDocument*>(this)->getXWeak()); +} + +SdrModel& SwXTextDocument::getSdrModelFromUnoModel() const +{ + assert(GetDocOrThrow().getIDocumentDrawModelAccess().GetOrCreateDrawModel()); + return *GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel(); +} + +SwXTextDocument::~SwXTextDocument() +{ + InitNewDoc(); + if(m_xNumFormatAgg.is()) + { + Reference< XInterface > x0; + m_xNumFormatAgg->setDelegator(x0); + m_xNumFormatAgg = nullptr; + } + m_pPrintUIOptions.reset(); + if (m_pRenderData && m_pRenderData->IsViewOptionAdjust()) + { // rhbz#827695: this can happen if the last page is not printed + // the SwViewShell has been deleted already by SwView::~SwView + // FIXME: replace this awful implementation of XRenderable with + // something less insane that has its own view + m_pRenderData->ViewOptionAdjustCrashPreventionKludge(); + } + m_pRenderData.reset(); +} + +SwXDocumentPropertyHelper * SwXTextDocument::GetPropertyHelper () +{ + if(!mxPropertyHelper.is()) + { + mxPropertyHelper = new SwXDocumentPropertyHelper(GetDocOrThrow()); + } + return mxPropertyHelper.get(); +} + +void SwXTextDocument::GetNumberFormatter() +{ + if(!IsValid()) + return; + + if(!m_xNumFormatAgg.is()) + { + if ( m_pDocShell->GetDoc() ) + { + rtl::Reference<SvNumberFormatsSupplierObj> pNumFormat = new SvNumberFormatsSupplierObj( + m_pDocShell->GetDoc()->GetNumberFormatter()); + m_xNumFormatAgg = pNumFormat; + } + if(m_xNumFormatAgg.is()) + m_xNumFormatAgg->setDelegator(getXWeak()); + } + else + { + const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); + Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType); + Reference< XUnoTunnel > xNumTunnel; + aNumTunnel >>= xNumTunnel; + SvNumberFormatsSupplierObj* pNumFormat + = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel); + OSL_ENSURE(pNumFormat, "No number formatter available"); + if (pNumFormat && !pNumFormat->GetNumberFormatter()) + pNumFormat->SetNumberFormatter(GetDocOrThrow().GetNumberFormatter()); + } +} + +Reference< XText > SwXTextDocument::getText() +{ + return getBodyText(); +} + +rtl::Reference< SwXBodyText > SwXTextDocument::getBodyText() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!m_xBodyText.is()) + { + m_xBodyText = new SwXBodyText(m_pDocShell->GetDoc()); + } + return m_xBodyText; +} + +void SwXTextDocument::reformat() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); +} + +void SwXTextDocument::lockControllers() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + maActionArr.emplace_front(new UnoActionContext(m_pDocShell->GetDoc())); +} + +void SwXTextDocument::unlockControllers() +{ + SolarMutexGuard aGuard; + if(maActionArr.empty()) + throw RuntimeException("Nothing to unlock"); + + maActionArr.pop_front(); +} + +sal_Bool SwXTextDocument::hasControllersLocked() +{ + SolarMutexGuard aGuard; + return !maActionArr.empty(); +} + +Reference< frame::XController > SwXTextDocument::getCurrentController() +{ + return SfxBaseModel::getCurrentController(); +} + +void SwXTextDocument::setCurrentController(const Reference< frame::XController > & xController) +{ + SfxBaseModel::setCurrentController(xController); +} + +Reference< XInterface > SwXTextDocument::getCurrentSelection() +{ + SolarMutexGuard aGuard; + Reference< XInterface > xRef; + if(IsValid()) + { + SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>)); + while(pView && pView->GetObjectShell() != m_pDocShell) + { + pView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>)); + } + if(pView) + { + Any aRef = pView->GetUNOObject()->getSelection(); + aRef >>= xRef; + } + } + return xRef; +} + +sal_Bool SwXTextDocument::attachResource(const OUString& aURL, const Sequence< beans::PropertyValue >& aArgs) +{ + return SfxBaseModel::attachResource(aURL, aArgs); +} + +OUString SwXTextDocument::getURL() +{ + return SfxBaseModel::getURL(); +} + +Sequence< beans::PropertyValue > SwXTextDocument::getArgs() +{ + return SfxBaseModel::getArgs(); +} + +void SwXTextDocument::connectController(const Reference< frame::XController > & xController) +{ + SfxBaseModel::connectController(xController); +} + +void SwXTextDocument::disconnectController(const Reference< frame::XController > & xController) +{ + SfxBaseModel::disconnectController(xController); +} + +void SwXTextDocument::dispose() +{ + // Delete UnoActionContexts before deleting the SwDoc, as the first has unowned pointers to the + // second. + maActionArr.clear(); + + SfxBaseModel::dispose(); +} + +void SwXTextDocument::close( sal_Bool bDeliverOwnership ) +{ + if(m_pDocShell) + { + uno::Sequence< uno::Any > aArgs; + m_pDocShell->CallAutomationDocumentEventSinks( "Close", aArgs ); + } + SolarMutexGuard aGuard; + if(IsValid() && m_pHiddenViewFrame) + lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell); + SfxBaseModel::close(bDeliverOwnership); +} + +void SwXTextDocument::addEventListener(const Reference< lang::XEventListener > & aListener) +{ + SfxBaseModel::addEventListener(aListener); +} + +void SwXTextDocument::removeEventListener(const Reference< lang::XEventListener > & aListener) +{ + SfxBaseModel::removeEventListener(aListener); +} + +Reference< XPropertySet > SwXTextDocument::getLineNumberingProperties() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + if(!mxXLineNumberingProperties.is()) + { + mxXLineNumberingProperties = new SwXLineNumberingProperties(m_pDocShell->GetDoc()); + } + return mxXLineNumberingProperties; +} + +Reference< XIndexReplace > SwXTextDocument::getChapterNumberingRules() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXChapterNumbering.is()) + { + mxXChapterNumbering = new SwXChapterNumbering(*m_pDocShell); + } + return mxXChapterNumbering; +} + +Reference< XIndexAccess > SwXTextDocument::getNumberingRules() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXNumberingRules.is() ) + { + mxXNumberingRules = new SwXNumberingRulesCollection( m_pDocShell->GetDoc() ); + } + return mxXNumberingRules; +} + +Reference< XIndexAccess > SwXTextDocument::getFootnotes() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXFootnotes.is()) + { + mxXFootnotes = new SwXFootnotes(false, m_pDocShell->GetDoc()); + } + return mxXFootnotes; +} + +Reference< XPropertySet > SAL_CALL + SwXTextDocument::getFootnoteSettings() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXFootnoteSettings.is()) + { + mxXFootnoteSettings = new SwXFootnoteProperties(m_pDocShell->GetDoc()); + } + return mxXFootnoteSettings; +} + +Reference< XIndexAccess > SwXTextDocument::getEndnotes() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXEndnotes.is()) + { + mxXEndnotes = new SwXFootnotes(true, m_pDocShell->GetDoc()); + } + return mxXEndnotes; +} + +Reference< XPropertySet > SwXTextDocument::getEndnoteSettings() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXEndnoteSettings.is()) + { + mxXEndnoteSettings = new SwXEndnoteProperties(m_pDocShell->GetDoc()); + } + return mxXEndnoteSettings; +} + +Reference< XIndexAccess > SwXTextDocument::getContentControls() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXContentControls.is()) + { + mxXContentControls = new SwXContentControls(m_pDocShell->GetDoc()); + } + return mxXContentControls; +} + +Reference< util::XReplaceDescriptor > SwXTextDocument::createReplaceDescriptor() +{ + return new SwXTextSearch; +} + +SwUnoCursor* SwXTextDocument::CreateCursorForSearch(Reference< XTextCursor > & xCursor) +{ + getText(); + XText *const pText = m_xBodyText.get(); + SwXBodyText* pBText = static_cast<SwXBodyText*>(pText); + rtl::Reference<SwXTextCursor> pXTextCursor = pBText->CreateTextCursor(true); + xCursor.set( static_cast<text::XWordCursor*>(pXTextCursor.get()) ); + + auto& rUnoCursor(pXTextCursor->GetCursor()); + rUnoCursor.SetRemainInSection(false); + return &rUnoCursor; +} + +sal_Int32 SwXTextDocument::replaceAll(const Reference< util::XSearchDescriptor > & xDesc) +{ + SolarMutexGuard aGuard; + SwXTextSearch* pSearch; + if (!IsValid() || !(pSearch = dynamic_cast<SwXTextSearch*>(xDesc.get()))) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + Reference< XTextCursor > xCursor; + auto pUnoCursor(CreateCursorForSearch(xCursor)); + int eRanges(FindRanges::InBody|FindRanges::InSelAll); + + i18nutil::SearchOptions2 aSearchOpt; + pSearch->FillSearchOptions( aSearchOpt ); + + SwDocPositions eStart = pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start; + SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End; + + // Search should take place anywhere + pUnoCursor->SetRemainInSection(false); + sal_Int32 nResult; + UnoActionContext aContext(m_pDocShell->GetDoc()); + //try attribute search first + if(pSearch->HasSearchAttributes()||pSearch->HasReplaceAttributes()) + { + auto& pool = GetDocOrThrow().GetAttrPool(); + SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1, + RES_PARATR_BEGIN, RES_PARATR_END-1, + RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSearch(pool); + SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1, + RES_PARATR_BEGIN, RES_PARATR_END-1, + RES_FRMATR_BEGIN, RES_FRMATR_END-1> aReplace(pool); + pSearch->FillSearchItemSet(aSearch); + pSearch->FillReplaceItemSet(aReplace); + bool bCancel; + nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, + eStart, eEnd, bCancel, + static_cast<FindRanges>(eRanges), + !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr, + &aReplace ); + } + else if(pSearch->m_bStyles) + { + SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc()); + SwTextFormatColl *pReplaceColl = lcl_GetParaStyle(pSearch->m_sReplaceText, pUnoCursor->GetDoc()); + + bool bCancel; + nResult = pUnoCursor->FindFormat(*pSearchColl, + eStart, eEnd, bCancel, + static_cast<FindRanges>(eRanges), pReplaceColl ); + + } + else + { + //todo/mba: assuming that notes should be omitted + bool bCancel; + nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/, + eStart, eEnd, bCancel, + static_cast<FindRanges>(eRanges), + true ); + } + return nResult; + +} + +Reference< util::XSearchDescriptor > SwXTextDocument::createSearchDescriptor() +{ + return new SwXTextSearch; +} + +// Used for findAll/First/Next + +SwUnoCursor* SwXTextDocument::FindAny(const Reference< util::XSearchDescriptor > & xDesc, + Reference< XTextCursor > & xCursor, + bool bAll, + sal_Int32& nResult, + Reference< XInterface > const & xLastResult) +{ + const auto pSearch = dynamic_cast<SwXTextSearch*>(xDesc.get()); + if(!IsValid() || !pSearch) + return nullptr; + + auto pUnoCursor(CreateCursorForSearch(xCursor)); + + bool bParentInExtra = false; + if(xLastResult.is()) + { + OTextCursorHelper* pPosCursor = dynamic_cast<OTextCursorHelper*>(xLastResult.get()); + SwPaM* pCursor = pPosCursor ? pPosCursor->GetPaM() : nullptr; + if(pCursor) + { + *pUnoCursor->GetPoint() = *pCursor->End(); + pUnoCursor->DeleteMark(); + } + else + { + SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xLastResult.get()); + if(!pRange) + return nullptr; + pRange->GetPositions(*pUnoCursor); + if(pUnoCursor->HasMark()) + { + if(*pUnoCursor->GetPoint() < *pUnoCursor->GetMark()) + pUnoCursor->Exchange(); + pUnoCursor->DeleteMark(); + } + } + const SwNode& rRangeNode = pUnoCursor->GetPointNode(); + bParentInExtra = rRangeNode.FindFlyStartNode() || + rRangeNode.FindFootnoteStartNode() || + rRangeNode.FindHeaderStartNode() || + rRangeNode.FindFooterStartNode() ; + } + + i18nutil::SearchOptions2 aSearchOpt; + pSearch->FillSearchOptions( aSearchOpt ); + +/** + * The following combinations are allowed: + * - Search in the body: -> FindRanges::InBody + * - Search all in the body: -> FindRanges::InBodyOnly | FindRanges::InSelAll + * - Search in selections: one / all -> FindRanges::InSel [ | FindRanges::InSelAll ] + * - Search outside the body: one / all -> FindRanges::InOther [ | FindRanges::InSelAll ] + * - Search everywhere all: -> FindRanges::InSelAll + */ + FindRanges eRanges(FindRanges::InBody); + if(bParentInExtra) + eRanges = FindRanges::InOther; + if(bAll) //always - everywhere? + eRanges = FindRanges::InSelAll; + SwDocPositions eStart = !bAll ? SwDocPositions::Curr : pSearch->m_bBack ? SwDocPositions::End : SwDocPositions::Start; + SwDocPositions eEnd = pSearch->m_bBack ? SwDocPositions::Start : SwDocPositions::End; + + nResult = 0; + for (int nSearchProc = 0; nSearchProc < 2; ++nSearchProc) + { + //try attribute search first + if(pSearch->HasSearchAttributes()) + { + SfxItemSetFixed< + RES_CHRATR_BEGIN, RES_CHRATR_END - 1, + RES_TXTATR_INETFMT, RES_TXTATR_CHARFMT, + RES_PARATR_BEGIN, RES_PARATR_END - 1, + RES_FRMATR_BEGIN, RES_FRMATR_END - 1> + aSearch( GetDocOrThrow().GetAttrPool() ); + pSearch->FillSearchItemSet(aSearch); + bool bCancel; + nResult = pUnoCursor->FindAttrs(aSearch, !pSearch->m_bStyles, + eStart, eEnd, bCancel, + eRanges, + !pSearch->m_sSearchText.isEmpty() ? &aSearchOpt : nullptr ); + } + else if(pSearch->m_bStyles) + { + SwTextFormatColl *pSearchColl = lcl_GetParaStyle(pSearch->m_sSearchText, pUnoCursor->GetDoc()); + //pSearch->sReplaceText + SwTextFormatColl *pReplaceColl = nullptr; + bool bCancel; + nResult = pUnoCursor->FindFormat(*pSearchColl, + eStart, eEnd, bCancel, + eRanges, pReplaceColl ); + } + else + { + //todo/mba: assuming that notes should be omitted + bool bCancel; + nResult = pUnoCursor->Find_Text(aSearchOpt, false/*bSearchInNotes*/, + eStart, eEnd, bCancel, + eRanges ); + } + if(nResult || (eRanges&(FindRanges::InSelAll|FindRanges::InOther))) + break; + //second step - find in other + eRanges = FindRanges::InOther; + } + return pUnoCursor; +} + +Reference< XIndexAccess > + SwXTextDocument::findAll(const Reference< util::XSearchDescriptor > & xDesc) +{ + SolarMutexGuard aGuard; + Reference< XInterface > xTmp; + sal_Int32 nResult = 0; + Reference< XTextCursor > xCursor; + auto pResultCursor(FindAny(xDesc, xCursor, true, nResult, xTmp)); + if(!pResultCursor) + throw RuntimeException("No result cursor"); + Reference< XIndexAccess > xRet = SwXTextRanges::Create( nResult ? &(*pResultCursor) : nullptr ); + return xRet; +} + +Reference< XInterface > SwXTextDocument::findFirst(const Reference< util::XSearchDescriptor > & xDesc) +{ + SolarMutexGuard aGuard; + Reference< XInterface > xTmp; + sal_Int32 nResult = 0; + Reference< XTextCursor > xCursor; + auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xTmp)); + if(!pResultCursor) + throw RuntimeException("No result cursor"); + Reference< XInterface > xRet; + if(nResult) + { + const uno::Reference< text::XText > xParent = + ::sw::CreateParentXText(GetDocOrThrow(), + *pResultCursor->GetPoint()); + xRet = *new SwXTextCursor(xParent, *pResultCursor); + } + return xRet; +} + +Reference< XInterface > SwXTextDocument::findNext(const Reference< XInterface > & xStartAt, + const Reference< util::XSearchDescriptor > & xDesc) +{ + SolarMutexGuard aGuard; + sal_Int32 nResult = 0; + Reference< XTextCursor > xCursor; + if(!xStartAt.is()) + throw RuntimeException("xStartAt missing"); + auto pResultCursor(FindAny(xDesc, xCursor, false, nResult, xStartAt)); + if(!pResultCursor) + throw RuntimeException("No result cursor"); + Reference< XInterface > xRet; + if(nResult) + { + const uno::Reference< text::XText > xParent = + ::sw::CreateParentXText(GetDocOrThrow(), + *pResultCursor->GetPoint()); + + xRet = *new SwXTextCursor(xParent, *pResultCursor); + } + return xRet; +} + +Sequence< beans::PropertyValue > SwXTextDocument::getPagePrintSettings() +{ + SolarMutexGuard aGuard; + Sequence< beans::PropertyValue > aSeq(9); + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + beans::PropertyValue* pArray = aSeq.getArray(); + SwPagePreviewPrtData aData; + const SwPagePreviewPrtData* pData = GetDocOrThrow().GetPreviewPrtData(); + if(pData) + aData = *pData; + Any aVal; + aVal <<= aData.GetRow(); + pArray[0] = beans::PropertyValue("PageRows", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= aData.GetCol(); + pArray[1] = beans::PropertyValue("PageColumns", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetLeftSpace())); + pArray[2] = beans::PropertyValue("LeftMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetRightSpace())); + pArray[3] = beans::PropertyValue("RightMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetTopSpace())); + pArray[4] = beans::PropertyValue("TopMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetBottomSpace())); + pArray[5] = beans::PropertyValue("BottomMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetHorzSpace())); + pArray[6] = beans::PropertyValue("HoriMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= static_cast<sal_Int32>(convertTwipToMm100(aData.GetVertSpace())); + pArray[7] = beans::PropertyValue("VertMargin", -1, aVal, PropertyState_DIRECT_VALUE); + aVal <<= aData.GetLandscape(); + pArray[8] = beans::PropertyValue("IsLandscape", -1, aVal, PropertyState_DIRECT_VALUE); + + return aSeq; +} + +static sal_uInt32 lcl_Any_To_ULONG(const Any& rValue, bool& bException) +{ + bException = false; + TypeClass eType = rValue.getValueType().getTypeClass(); + + sal_uInt32 nRet = 0; + if( eType == TypeClass_UNSIGNED_LONG ) + rValue >>= nRet; + else + { + sal_Int32 nVal=0; + bException = !(rValue >>= nVal); + if( !bException ) + nRet = static_cast<sal_uInt32>(nVal); + } + + return nRet; +} + +static OUString lcl_CreateOutlineString(const size_t nIndex, const SwDoc* pDoc) +{ + OUStringBuffer sEntry; + const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); + const SwNumRule* pOutlRule = pDoc->GetOutlineNumRule(); + const SwTextNode * pTextNd = rOutlineNodes[ nIndex ]->GetTextNode(); + SwNumberTree::tNumberVector aNumVector = pTextNd->GetNumberVector(); + if( pOutlRule && pTextNd->GetNumRule()) + for( int nLevel = 0; + nLevel <= pTextNd->GetActualListLevel(); + nLevel++ ) + { + tools::Long nVal = aNumVector[nLevel]; + nVal ++; + nVal -= pOutlRule->Get(nLevel).GetStart(); + sEntry.append( OUString::number(nVal) + "."); + } + OUString sOutlineText = pDoc->getIDocumentOutlineNodes().getOutlineText( + nIndex, pDoc->GetDocShell()->GetWrtShell()->GetLayout(), false); + sEntry.append(sOutlineText); + return sEntry.makeStringAndClear(); +} + +void SwXTextDocument::setPagePrintSettings(const Sequence< beans::PropertyValue >& aSettings) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwPagePreviewPrtData aData; + SwDoc& rDoc = GetDocOrThrow(); + //if only a few properties are coming, then use the current settings + const SwPagePreviewPrtData* pData = rDoc.GetPreviewPrtData(); + if(pData) + aData = *pData; + for(const beans::PropertyValue& rProperty : aSettings) + { + OUString sName = rProperty.Name; + const Any& rVal = rProperty.Value; + bool bException; + sal_uInt32 nVal = lcl_Any_To_ULONG(rVal, bException); + if( sName == "PageRows" ) + { + if(!nVal || nVal > 0xff) + throw RuntimeException("Invalid value"); + aData.SetRow(nVal); + } + else if(sName == "PageColumns") + { + if(!nVal || nVal > 0xff) + throw RuntimeException("Invalid value"); + aData.SetCol(nVal); + } + else if(sName == "LeftMargin") + { + aData.SetLeftSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "RightMargin") + { + aData.SetRightSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "TopMargin") + { + aData.SetTopSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "BottomMargin") + { + aData.SetBottomSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "HoriMargin") + { + aData.SetHorzSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "VertMargin") + { + aData.SetVertSpace(o3tl::toTwips(nVal, o3tl::Length::mm100)); + } + else if(sName == "IsLandscape") + { + std::optional<const bool> b = o3tl::tryAccess<bool>(rVal); + bException = !b.has_value(); + if (b) + { + aData.SetLandscape(*b); + } + } + else + bException = true; + if(bException) + throw RuntimeException(); + } + rDoc.SetPreviewPrtData(&aData); + +} + +void SwXTextDocument::printPages(const Sequence< beans::PropertyValue >& xOptions) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SfxViewFrame* pFrame = SfxViewFrame::LoadHiddenDocument( *m_pDocShell, SfxInterfaceId(7) ); + SfxRequest aReq(FN_PRINT_PAGEPREVIEW, SfxCallMode::SYNCHRON, + GetDocOrThrow().GetAttrPool()); + aReq.AppendItem(SfxBoolItem(FN_PRINT_PAGEPREVIEW, true)); + + for ( const beans::PropertyValue &rProp : xOptions ) + { + // get Property-Value from options + Any aValue( rProp.Value ); + + // FileName-Property? + if ( rProp.Name == UNO_NAME_FILE_NAME ) + { + OUString sFileURL; + if ( rProp.Value >>= sFileURL ) + { + // Convert the File URL into a system dependent path, as the SalPrinter expects + OUString sSystemPath; + FileBase::getSystemPathFromFileURL ( sFileURL, sSystemPath ); + aReq.AppendItem(SfxStringItem( SID_FILE_NAME, sSystemPath ) ); + } + else if ( rProp.Value.getValueType() != cppu::UnoType<void>::get() ) + throw IllegalArgumentException(); + } + + // CopyCount-Property + else if ( rProp.Name == UNO_NAME_COPY_COUNT ) + { + sal_Int32 nCopies = 0; + aValue >>= nCopies; + aReq.AppendItem(SfxInt16Item( SID_PRINT_COPIES, static_cast<sal_Int16>(nCopies) ) ); + } + + // Collate-Property + else if ( rProp.Name == UNO_NAME_COLLATE ) + { + std::optional<const bool> b = o3tl::tryAccess<bool>(rProp.Value); + if ( !b.has_value() ) + throw IllegalArgumentException(); + aReq.AppendItem(SfxBoolItem( SID_PRINT_COLLATE, *b ) ); + + } + + // Sort-Property + else if ( rProp.Name == UNO_NAME_SORT ) + { + std::optional<const bool> b = o3tl::tryAccess<bool>(rProp.Value); + if ( !b.has_value() ) + throw IllegalArgumentException(); + + aReq.AppendItem(SfxBoolItem( SID_PRINT_SORT, *b ) ); + } + + // Pages-Property + else if ( rProp.Name == UNO_NAME_PAGES ) + { + OUString sTmp; + if ( !(rProp.Value >>= sTmp) ) + throw IllegalArgumentException(); + + aReq.AppendItem( SfxStringItem( SID_PRINT_PAGES, sTmp ) ); + + } + } + + // #i117783# + m_bApplyPagePrintSettingsFromXPagePrintable = true; + pFrame->GetViewShell()->ExecuteSlot(aReq); + // Frame close + pFrame->DoClose(); + +} + +Reference< XNameAccess > SwXTextDocument::getReferenceMarks() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXReferenceMarks.is()) + { + mxXReferenceMarks = new SwXReferenceMarks(m_pDocShell->GetDoc()); + } + return mxXReferenceMarks; +} + +Reference< XEnumerationAccess > SwXTextDocument::getTextFields() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFieldTypes.is()) + { + mxXTextFieldTypes = new SwXTextFieldTypes(m_pDocShell->GetDoc()); + } + return mxXTextFieldTypes; +} + +Reference< XNameAccess > SwXTextDocument::getTextFieldMasters() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFieldMasters.is()) + { + mxXTextFieldMasters = new SwXTextFieldMasters(m_pDocShell->GetDoc()); + } + return mxXTextFieldMasters; +} + +Reference< XNameAccess > SwXTextDocument::getEmbeddedObjects() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXEmbeddedObjects.is()) + { + mxXEmbeddedObjects = new SwXTextEmbeddedObjects(m_pDocShell->GetDoc()); + } + return mxXEmbeddedObjects; +} + +Reference< XNameAccess > SwXTextDocument::getBookmarks() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXBookmarks.is()) + { + mxXBookmarks = new SwXBookmarks(m_pDocShell->GetDoc()); + } + return mxXBookmarks; +} + +Reference< XNameAccess > SwXTextDocument::getTextSections() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextSections.is()) + { + mxXTextSections = new SwXTextSections(m_pDocShell->GetDoc()); + } + return mxXTextSections; +} + +Reference< XNameAccess > SwXTextDocument::getTextTables() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextTables.is()) + { + mxXTextTables = new SwXTextTables(m_pDocShell->GetDoc()); + } + return mxXTextTables; +} + +Reference< XNameAccess > SwXTextDocument::getGraphicObjects() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXGraphicObjects.is()) + { + mxXGraphicObjects = new SwXTextGraphicObjects(m_pDocShell->GetDoc()); + } + return mxXGraphicObjects; +} + +Reference< XNameAccess > SwXTextDocument::getTextFrames() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXTextFrames.is()) + { + mxXTextFrames = new SwXTextFrames(m_pDocShell->GetDoc()); + } + return mxXTextFrames; +} + +Reference< XNameAccess > SwXTextDocument::getStyleFamilies() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXStyleFamilies.is()) + { + mxXStyleFamilies = new SwXStyleFamilies(*m_pDocShell); + } + return mxXStyleFamilies; +} + +uno::Reference< style::XAutoStyles > SwXTextDocument::getAutoStyles( ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!mxXAutoStyles.is()) + { + mxXAutoStyles = new SwXAutoStyles(*m_pDocShell); + } + return mxXAutoStyles; + +} + +Reference< drawing::XDrawPage > SwXTextDocument::getDrawPage() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + if(!m_xDrawPage.is()) + { + SwDoc& rDoc = GetDocOrThrow(); + // #i52858# + SwDrawModel* pModel = rDoc.getIDocumentDrawModelAccess().GetOrCreateDrawModel(); + SdrPage* pPage = pModel->GetPage( 0 ); + m_xDrawPage = new SwFmDrawPage(&rDoc, pPage); + } + return m_xDrawPage; +} + +namespace { + +class SwDrawPagesObj : public cppu::WeakImplHelper< + css::drawing::XDrawPages, + css::lang::XServiceInfo> +{ +private: + css::uno::Reference< css::drawing::XDrawPageSupplier > m_xDoc; +public: + SwDrawPagesObj(css::uno::Reference< css::drawing::XDrawPageSupplier > xDoc) : m_xDoc(std::move(xDoc)) {} + + // XDrawPages + virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL + insertNewByIndex(sal_Int32 /*nIndex*/) override { throw css::lang::NoSupportException(); } + + virtual void SAL_CALL remove(const css::uno::Reference< css::drawing::XDrawPage >& /*xPage*/) override + { + throw css::lang::NoSupportException(); + } + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount() override { return 1; } + + virtual css::uno::Any SAL_CALL getByIndex(sal_Int32 Index) override + { + if (Index != 0) + throw css::lang::IndexOutOfBoundsException("Writer documents have only one DrawPage!"); + return css::uno::Any(m_xDoc->getDrawPage()); + } + + // XElementAccess + virtual css::uno::Type SAL_CALL getElementType() override + { + return cppu::UnoType<drawing::XDrawPage>::get(); + } + + virtual sal_Bool SAL_CALL hasElements() override { return true; } + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override + { + return "SwDrawPagesObj"; + } + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override + { + return { "com.sun.star.drawing.DrawPages" }; + } +}; + +} + +// XDrawPagesSupplier + +uno::Reference<drawing::XDrawPages> SAL_CALL SwXTextDocument::getDrawPages() +{ + SolarMutexGuard aGuard; + return new SwDrawPagesObj(this); +} + +void SwXTextDocument::Invalidate() +{ + m_bObjectValid = false; + if(m_xNumFormatAgg.is()) + { + const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); + Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType); + Reference< XUnoTunnel > xNumTunnel; + aNumTunnel >>= xNumTunnel; + SvNumberFormatsSupplierObj* pNumFormat + = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel); + OSL_ENSURE(pNumFormat, "No number formatter available"); + if (pNumFormat) + pNumFormat->SetNumberFormatter(nullptr); + OSL_ENSURE(pNumFormat, "No number formatter available"); + } + InitNewDoc(); + m_pDocShell = nullptr; + lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this)); + std::unique_lock aGuard(m_pImpl->m_Mutex); + m_pImpl->m_RefreshListeners.disposeAndClear(aGuard, ev); +} + +void SwXTextDocument::Reactivate(SwDocShell* pNewDocShell) +{ + if(m_pDocShell && m_pDocShell != pNewDocShell) + Invalidate(); + m_pDocShell = pNewDocShell; + m_bObjectValid = true; +} + +void SwXTextDocument::InitNewDoc() +{ + // first invalidate all collections, then delete references and Set to zero + if(mxXTextTables.is()) + { + XNameAccess* pTables = mxXTextTables.get(); + static_cast<SwXTextTables*>(pTables)->Invalidate(); + mxXTextTables.clear(); + } + + if(mxXTextFrames.is()) + { + XNameAccess* pFrames = mxXTextFrames.get(); + static_cast<SwXTextFrames*>(pFrames)->Invalidate(); + mxXTextFrames.clear(); + } + + if(mxXGraphicObjects.is()) + { + XNameAccess* pFrames = mxXGraphicObjects.get(); + static_cast<SwXTextGraphicObjects*>(pFrames)->Invalidate(); + mxXGraphicObjects.clear(); + } + + if(mxXEmbeddedObjects.is()) + { + XNameAccess* pOLE = mxXEmbeddedObjects.get(); + static_cast<SwXTextEmbeddedObjects*>(pOLE)->Invalidate(); + mxXEmbeddedObjects.clear(); + } + + m_xBodyText = nullptr; + + if(m_xNumFormatAgg.is()) + { + const uno::Type& rTunnelType = cppu::UnoType<XUnoTunnel>::get(); + Any aNumTunnel = m_xNumFormatAgg->queryAggregation(rTunnelType); + Reference< XUnoTunnel > xNumTunnel; + aNumTunnel >>= xNumTunnel; + SvNumberFormatsSupplierObj* pNumFormat + = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xNumTunnel); + OSL_ENSURE(pNumFormat, "No number formatter available"); + if (pNumFormat) + pNumFormat->SetNumberFormatter(nullptr); + } + + if(mxXTextFieldTypes.is()) + { + XEnumerationAccess* pT = mxXTextFieldTypes.get(); + static_cast<SwXTextFieldTypes*>(pT)->Invalidate(); + mxXTextFieldTypes.clear(); + } + + if(mxXTextFieldMasters.is()) + { + XNameAccess* pT = mxXTextFieldMasters.get(); + static_cast<SwXTextFieldMasters*>(pT)->Invalidate(); + mxXTextFieldMasters.clear(); + } + + if(mxXTextSections.is()) + { + XNameAccess* pSect = mxXTextSections.get(); + static_cast<SwXTextSections*>(pSect)->Invalidate(); + mxXTextSections.clear(); + } + + if(m_xDrawPage.is()) + { + // #i91798#, #i91895# + // dispose XDrawPage here. We are the owner and know that it is no longer in a valid condition. + m_xDrawPage->dispose(); + m_xDrawPage->InvalidateSwDoc(); + m_xDrawPage.clear(); + } + + if ( mxXNumberingRules.is() ) + { + XIndexAccess* pNum = mxXNumberingRules.get(); + static_cast<SwXNumberingRulesCollection*>(pNum)->Invalidate(); + mxXNumberingRules.clear(); + } + + if(mxXFootnotes.is()) + { + XIndexAccess* pFootnote = mxXFootnotes.get(); + static_cast<SwXFootnotes*>(pFootnote)->Invalidate(); + mxXFootnotes.clear(); + } + + if(mxXEndnotes.is()) + { + XIndexAccess* pFootnote = mxXEndnotes.get(); + static_cast<SwXFootnotes*>(pFootnote)->Invalidate(); + mxXEndnotes.clear(); + } + + if(mxXContentControls.is()) + { + XIndexAccess* pContentControls = mxXContentControls.get(); + static_cast<SwXContentControls*>(pContentControls)->Invalidate(); + mxXContentControls.clear(); + } + + if(mxXDocumentIndexes.is()) + { + XIndexAccess* pIdxs = mxXDocumentIndexes.get(); + static_cast<SwXDocumentIndexes*>(pIdxs)->Invalidate(); + mxXDocumentIndexes.clear(); + } + + if(mxXStyleFamilies.is()) + { + XNameAccess* pStyles = mxXStyleFamilies.get(); + static_cast<SwXStyleFamilies*>(pStyles)->Invalidate(); + mxXStyleFamilies.clear(); + } + if(mxXAutoStyles.is()) + { + XNameAccess* pStyles = mxXAutoStyles.get(); + static_cast<SwXAutoStyles*>(pStyles)->Invalidate(); + mxXAutoStyles.clear(); + } + + if(mxXBookmarks.is()) + { + XNameAccess* pBm = mxXBookmarks.get(); + static_cast<SwXBookmarks*>(pBm)->Invalidate(); + mxXBookmarks.clear(); + } + + if(mxXChapterNumbering.is()) + { + XIndexReplace* pCh = mxXChapterNumbering.get(); + static_cast<SwXChapterNumbering*>(pCh)->Invalidate(); + mxXChapterNumbering.clear(); + } + + if(mxXFootnoteSettings.is()) + { + XPropertySet* pFntSet = mxXFootnoteSettings.get(); + static_cast<SwXFootnoteProperties*>(pFntSet)->Invalidate(); + mxXFootnoteSettings.clear(); + } + + if(mxXEndnoteSettings.is()) + { + XPropertySet* pEndSet = mxXEndnoteSettings.get(); + static_cast<SwXEndnoteProperties*>(pEndSet)->Invalidate(); + mxXEndnoteSettings.clear(); + } + + if(mxXLineNumberingProperties.is()) + { + XPropertySet* pLine = mxXLineNumberingProperties.get(); + static_cast<SwXLineNumberingProperties*>(pLine)->Invalidate(); + mxXLineNumberingProperties.clear(); + } + if(mxXReferenceMarks.is()) + { + XNameAccess* pMarks = mxXReferenceMarks.get(); + static_cast<SwXReferenceMarks*>(pMarks)->Invalidate(); + mxXReferenceMarks.clear(); + } + if(mxLinkTargetSupplier.is()) + { + XNameAccess* pAccess = mxLinkTargetSupplier.get(); + static_cast<SwXLinkTargetSupplier*>(pAccess)->Invalidate(); + mxLinkTargetSupplier.clear(); + } + if(mxXRedlines.is()) + { + XEnumerationAccess* pMarks = mxXRedlines.get(); + static_cast<SwXRedlines*>(pMarks)->Invalidate(); + mxXRedlines.clear(); + } + if(mxPropertyHelper.is()) + { + mxPropertyHelper->Invalidate(); + mxPropertyHelper.clear(); + } +} + +css::uno::Reference<css::uno::XInterface> SwXTextDocument::create( + OUString const & rServiceName, + css::uno::Sequence<css::uno::Any> const * arguments) +{ + SolarMutexGuard aGuard; + if (!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SwServiceType nType = SwXServiceProvider::GetProviderType(rServiceName); + if (nType != SwServiceType::Invalid) + { + return SwXServiceProvider::MakeInstance(nType, GetDocOrThrow()); + } + if (rServiceName == "com.sun.star.drawing.DashTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Dash); + } + if (rServiceName == "com.sun.star.drawing.GradientTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Gradient); + } + if (rServiceName == "com.sun.star.drawing.HatchTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Hatch); + } + if (rServiceName == "com.sun.star.drawing.BitmapTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Bitmap); + } + if (rServiceName == "com.sun.star.drawing.TransparencyGradientTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::TransGradient); + } + if (rServiceName == "com.sun.star.drawing.MarkerTable") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Marker); + } + if (rServiceName == "com.sun.star.drawing.Defaults") + { + return GetPropertyHelper()->GetDrawTable(SwCreateDrawTable::Defaults); + } + if (rServiceName == "com.sun.star.document.Settings") + { + return Reference<XInterface>(*new SwXDocumentSettings(this)); + } + if (rServiceName == "com.sun.star.document.ImportEmbeddedObjectResolver") + { + return cppu::getXWeak( + new SvXMLEmbeddedObjectHelper( + *m_pDocShell, SvXMLEmbeddedObjectHelperMode::Read)); + } + if (rServiceName == "com.sun.star.text.DocumentSettings") + { + return Reference<XInterface>(*new SwXDocumentSettings(this)); + } + if (rServiceName == "com.sun.star.chart2.data.DataProvider") + { + return Reference<XInterface>( + static_cast<chart2::data::XDataProvider *>( + m_pDocShell->getIDocumentChartDataProviderAccess(). + GetChartDataProvider())); + } + if (!rServiceName.startsWith("com.sun.star.") + || rServiceName.endsWith(".OLE2Shape")) + { + // We do not want to insert OLE2 Shapes (e.g., + // "com.sun.star.drawing.OLE2Shape", ...) like this (by creating them + // with the documents factory and adding the shapes to the draw page); + // for inserting OLE objects the proper way is to use + // "com.sun.star.text.TextEmbeddedObject": + throw ServiceNotRegisteredException(); + } + // The XML import is allowed to create instances of + // "com.sun.star.drawing.OLE2Shape"; thus, a temporary service name is + // introduced to make this possible: + OUString aTmpServiceName(rServiceName); + if (rServiceName == "com.sun.star.drawing.temporaryForXMLImportOLE2Shape") + { + aTmpServiceName = "com.sun.star.drawing.OLE2Shape"; + } + Reference<XInterface> xTmp( + arguments == nullptr + ? SvxFmMSFactory::createInstance(aTmpServiceName) + : SvxFmMSFactory::createInstanceWithArguments( + aTmpServiceName, *arguments)); + if (rServiceName == "com.sun.star.drawing.GroupShape" + || rServiceName == "com.sun.star.drawing.Shape3DSceneObject") + { + return *new SwXGroupShape(xTmp, m_pDocShell->GetDoc()); + } + if (rServiceName.startsWith("com.sun.star.drawing.")) + { + return *new SwXShape(xTmp, m_pDocShell->GetDoc()); + } + return xTmp; +} + +Reference< XInterface > SwXTextDocument::createInstance(const OUString& rServiceName) +{ + return create(rServiceName, nullptr); +} + +Reference< XInterface > SwXTextDocument::createInstanceWithArguments( + const OUString& ServiceSpecifier, + const Sequence< Any >& Arguments) +{ + return create(ServiceSpecifier, &Arguments); +} + +Sequence< OUString > SwXTextDocument::getAvailableServiceNames() +{ + static Sequence< OUString > aServices; + if ( !aServices.hasElements() ) + { + Sequence< OUString > aRet = SvxFmMSFactory::getAvailableServiceNames(); + auto i = comphelper::findValue(aRet, "com.sun.star.drawing.OLE2Shape"); + if (i != -1) + { + auto nLength = aRet.getLength(); + aRet.getArray()[i] = aRet[nLength - 1]; + aRet.realloc( nLength - 1 ); + } + Sequence< OUString > aOwn = SwXServiceProvider::GetAllServiceNames(); + aServices = comphelper::concatSequences(aRet, aOwn); + } + + return aServices; +} + +OUString SwXTextDocument::getImplementationName() +{ + return "SwXTextDocument"; + /* // Matching the .component information: + return dynamic_cast<SwGlobalDocShell*>( pDocShell ) != nullptr + ? OUString("com.sun.star.comp.Writer.GlobalDocument") + : dynamic_cast<SwWebDocShell*>( pDocShell ) != nullptr + ? OUString("com.sun.star.comp.Writer.WebDocument") + : OUString("com.sun.star.comp.Writer.TextDocument"); + */ +} + +sal_Bool SwXTextDocument::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXTextDocument::getSupportedServiceNames() +{ + bool bWebDoc = (dynamic_cast<SwWebDocShell*>( m_pDocShell) != nullptr ); + bool bGlobalDoc = (dynamic_cast<SwGlobalDocShell*>( m_pDocShell) != nullptr ); + bool bTextDoc = (!bWebDoc && !bGlobalDoc); + + Sequence< OUString > aRet (3); + OUString* pArray = aRet.getArray(); + + pArray[0] = "com.sun.star.document.OfficeDocument"; + pArray[1] = "com.sun.star.text.GenericTextDocument"; + + if (bTextDoc) + pArray[2] = "com.sun.star.text.TextDocument"; + else if (bWebDoc) + pArray[2] = "com.sun.star.text.WebDocument"; + else if (bGlobalDoc) + pArray[2] = "com.sun.star.text.GlobalDocument"; + + return aRet; +} + +Reference< XIndexAccess > SwXTextDocument::getDocumentIndexes() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + if(!mxXDocumentIndexes.is()) + { + mxXDocumentIndexes = new SwXDocumentIndexes(m_pDocShell->GetDoc()); + } + return mxXDocumentIndexes; +} + +Reference< XPropertySetInfo > SwXTextDocument::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXTextDocument::setPropertyValue(const OUString& rPropertyName, const Any& aValue) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + if(pEntry->nFlags & PropertyAttribute::READONLY) + throw PropertyVetoException(); + switch(pEntry->nWID) + { + case WID_DOC_CHAR_COUNT : + case WID_DOC_PARA_COUNT : + case WID_DOC_WORD_COUNT : + throw RuntimeException( + "bad WID", + getXWeak()); + case WID_DOC_WORD_SEPARATOR : + { + OUString sDelim; + aValue >>= sDelim; + SW_MOD()->GetModuleConfig()->SetWordDelimiter(sDelim); + } + break; + case WID_DOC_CHANGES_RECORD: + case WID_DOC_CHANGES_SHOW: + { + SwDoc& rDoc = GetDocOrThrow(); + sw::DocumentRedlineManager& rRedlineManager = rDoc.GetDocumentRedlineManager(); + bool bSet = *o3tl::doAccess<bool>(aValue); + RedlineFlags eMode = rRedlineManager.GetRedlineFlags(); + if(WID_DOC_CHANGES_SHOW == pEntry->nWID) + { + eMode |= RedlineFlags(RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); + if( !bSet ) + rRedlineManager.SetHideRedlines(true); + } + else if(WID_DOC_CHANGES_RECORD == pEntry->nWID) + { + eMode = bSet ? eMode|RedlineFlags::On : eMode&~RedlineFlags::On; + } + rRedlineManager.SetRedlineFlags(eMode); + } + break; + case WID_DOC_CHANGES_PASSWORD: + { + Sequence <sal_Int8> aNew; + if(aValue >>= aNew) + { + auto& rRedlineAccess = GetDocOrThrow().getIDocumentRedlineAccess(); + rRedlineAccess.SetRedlinePassword(aNew); + if(aNew.hasElements()) + { + RedlineFlags eMode = rRedlineAccess.GetRedlineFlags(); + eMode |= RedlineFlags::On; + rRedlineAccess.SetRedlineFlags(eMode); + } + } + } + break; + case WID_DOC_AUTO_MARK_URL : + { + OUString sURL; + aValue >>= sURL; + GetDocOrThrow().SetTOIAutoMarkURL(sURL); + } + break; + case WID_DOC_HIDE_TIPS : + SW_MOD()->GetModuleConfig()->SetHideFieldTips(*o3tl::doAccess<bool>(aValue)); + break; + case WID_DOC_REDLINE_DISPLAY: + { + auto& rRedlineAccess = GetDocOrThrow().getIDocumentRedlineAccess(); + RedlineFlags eRedMode = rRedlineAccess.GetRedlineFlags(); + eRedMode = eRedMode & (~RedlineFlags::ShowMask); + sal_Int16 nSet = 0; + aValue >>= nSet; + switch(nSet) + { + case RedlineDisplayType::NONE: break; + case RedlineDisplayType::INSERTED: eRedMode |= RedlineFlags::ShowInsert; break; + case RedlineDisplayType::REMOVED: eRedMode |= RedlineFlags::ShowDelete; break; + case RedlineDisplayType:: + INSERTED_AND_REMOVED: eRedMode |= RedlineFlags::ShowInsert|RedlineFlags::ShowDelete; + break; + default: throw IllegalArgumentException(); + } + rRedlineAccess.SetRedlineFlags(eRedMode); + } + break; + case WID_DOC_TWO_DIGIT_YEAR: + { + sal_Int16 nYear = 0; + aValue >>= nYear; + SfxRequest aRequest ( SID_ATTR_YEAR2000, SfxCallMode::SLOT, GetDocOrThrow().GetAttrPool()); + aRequest.AppendItem(SfxUInt16Item( SID_ATTR_YEAR2000, static_cast < sal_uInt16 > ( nYear ) ) ); + m_pDocShell->Execute ( aRequest ); + } + break; + case WID_DOC_AUTOMATIC_CONTROL_FOCUS: + { + auto& rDrawModelAccess = GetDocOrThrow().getIDocumentDrawModelAccess(); + bool bAuto = *o3tl::doAccess<bool>(aValue); + // if setting to true, and we don't have an + // SdrModel, then we are changing the default and + // must thus create an SdrModel, if we don't have an + // SdrModel and we are leaving the default at false, + // we don't need to make an SdrModel and can do nothing + // #i52858# - method name changed + SwDrawModel* pDrawDoc + = bAuto ? rDrawModelAccess.GetOrCreateDrawModel() : rDrawModelAccess.GetDrawModel(); + + if ( nullptr != pDrawDoc ) + pDrawDoc->SetAutoControlFocus( bAuto ); + } + break; + case WID_DOC_APPLY_FORM_DESIGN_MODE: + { + auto& rDrawModelAccess = GetDocOrThrow().getIDocumentDrawModelAccess(); + bool bMode = *o3tl::doAccess<bool>(aValue); + // if setting to false, and we don't have an + // SdrModel, then we are changing the default and + // must thus create an SdrModel, if we don't have an + // SdrModel and we are leaving the default at true, + // we don't need to make an SdrModel and can do + // nothing + // #i52858# - method name changed + SwDrawModel* pDrawDoc + = bMode ? rDrawModelAccess.GetDrawModel() : rDrawModelAccess.GetOrCreateDrawModel(); + + if ( nullptr != pDrawDoc ) + pDrawDoc->SetOpenInDesignMode( bMode ); + } + break; + // #i42634# New property to set the bInReading + // flag at the document, used during binary import + case WID_DOC_LOCK_UPDATES : + { + bool bBool (false); + if( aValue >>= bBool ) + { + GetDocOrThrow().SetInReading( bBool ); + } + } + break; + case WID_DOC_WRITERFILTER: + { + SwDoc& rDoc = GetDocOrThrow(); + bool bBool = {}; + if (aValue >>= bBool) + { // HACK: writerfilter has to use API to set this :( + bool bOld = rDoc.IsInWriterfilterImport(); + rDoc.SetInWriterfilterImport(bBool); + if (bOld && !bBool) + { + rDoc.getIDocumentFieldsAccess().SetFieldsDirty(false, nullptr, SwNodeOffset(0)); + } + } + } + break; + case WID_DOC_BUILDID: + aValue >>= maBuildId; + break; + + case WID_DOC_DEFAULT_PAGE_MODE: + { + bool bDefaultPageMode( false ); + aValue >>= bDefaultPageMode; + GetDocOrThrow().SetDefaultPageMode( bDefaultPageMode ); + } + break; + case WID_DOC_INTEROP_GRAB_BAG: + setGrabBagItem(aValue); + break; + + default: + { + SwDoc& rDoc = GetDocOrThrow(); + const SfxPoolItem& rItem = rDoc.GetDefault(pEntry->nWID); + std::unique_ptr<SfxPoolItem> pNewItem(rItem.Clone()); + pNewItem->PutValue(aValue, pEntry->nMemberId); + rDoc.SetDefault(*pNewItem); + } + } +} + +Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + if (rPropertyName == "ODFExport_ListNodes") + { + // A hack to avoid writing random list ids to ODF when they are not referred later + // see XMLTextParagraphExport::DocumentListNodes ctor + + // Sequence of nodes, each of them represented by three-element sequence: + // [ index, styleIntPtr, list_id ] + std::vector<css::uno::Sequence<css::uno::Any>> nodes; + + const SwDoc& rDoc = GetDocOrThrow(); + for (const SwNumRule* pNumRule : rDoc.GetNumRuleTable()) + { + SwNumRule::tTextNodeList textNodes; + pNumRule->GetTextNodeList(textNodes); + css::uno::Any styleIntPtr(reinterpret_cast<sal_uInt64>(pNumRule)); + + for (const SwTextNode* pTextNode : textNodes) + { + css::uno::Any index(pTextNode->GetIndex().get()); + css::uno::Any list_id(pTextNode->GetListId()); + + nodes.push_back({ index, styleIntPtr, list_id }); + } + } + return css::uno::Any(comphelper::containerToSequence(nodes)); + } + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + Any aAny; + switch(pEntry->nWID) + { + case WID_DOC_ISTEMPLATEID : + aAny <<= m_pDocShell->IsTemplate(); + break; + case WID_DOC_CHAR_COUNT : + case WID_DOC_PARA_COUNT : + case WID_DOC_WORD_COUNT : + { + const SwDocStat& rStat(GetDocOrThrow().getIDocumentStatistics().GetUpdatedDocStat( false, true )); + sal_Int32 nValue; + switch(pEntry->nWID) + { + case WID_DOC_CHAR_COUNT :nValue = rStat.nChar;break; + case WID_DOC_PARA_COUNT :nValue = rStat.nPara;break; + case WID_DOC_WORD_COUNT :nValue = rStat.nWord;break; + } + aAny <<= nValue; + } + break; + case WID_DOC_WORD_SEPARATOR : + { + aAny <<= SW_MOD()->GetDocStatWordDelim(); + } + break; + case WID_DOC_CHANGES_RECORD: + case WID_DOC_CHANGES_SHOW: + { + const RedlineFlags eMode = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineFlags(); + bool bSet = false; + if(WID_DOC_CHANGES_SHOW == pEntry->nWID) + { + bSet = IDocumentRedlineAccess::IsShowChanges(eMode); + } + else if(WID_DOC_CHANGES_RECORD == pEntry->nWID) + { + bSet = bool(eMode & RedlineFlags::On); + } + aAny <<= bSet; + } + break; + case WID_DOC_CHANGES_PASSWORD: + aAny <<= GetDocOrThrow().getIDocumentRedlineAccess().GetRedlinePassword(); + break; + case WID_DOC_AUTO_MARK_URL : + aAny <<= GetDocOrThrow().GetTOIAutoMarkURL(); + break; + case WID_DOC_HIDE_TIPS : + aAny <<= SW_MOD()->GetModuleConfig()->IsHideFieldTips(); + break; + case WID_DOC_REDLINE_DISPLAY: + { + RedlineFlags eRedMode = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineFlags(); + eRedMode = eRedMode & RedlineFlags::ShowMask; + sal_Int16 nRet = RedlineDisplayType::NONE; + if(RedlineFlags::ShowInsert == eRedMode) + nRet = RedlineDisplayType::INSERTED; + else if(RedlineFlags::ShowDelete == eRedMode) + nRet = RedlineDisplayType::REMOVED; + else if(RedlineFlags::ShowMask == eRedMode) + nRet = RedlineDisplayType::INSERTED_AND_REMOVED; + aAny <<= nRet; + } + break; + case WID_DOC_FORBIDDEN_CHARS: + { + GetPropertyHelper(); + Reference<XForbiddenCharacters> xRet = mxPropertyHelper; + aAny <<= xRet; + } + break; + case WID_DOC_TWO_DIGIT_YEAR: + { + aAny <<= static_cast < sal_Int16 > (GetDocOrThrow().GetNumberFormatter ()->GetYear2000()); + } + break; + case WID_DOC_AUTOMATIC_CONTROL_FOCUS: + { + SwDrawModel * pDrawDoc = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel(); + bool bAuto; + if ( nullptr != pDrawDoc ) + bAuto = pDrawDoc->GetAutoControlFocus(); + else + bAuto = false; + aAny <<= bAuto; + } + break; + case WID_DOC_APPLY_FORM_DESIGN_MODE: + { + SwDrawModel * pDrawDoc = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel(); + bool bMode; + if ( nullptr != pDrawDoc ) + bMode = pDrawDoc->GetOpenInDesignMode(); + else + bMode = true; + aAny <<= bMode; + } + break; + case WID_DOC_BASIC_LIBRARIES: + aAny <<= m_pDocShell->GetBasicContainer(); + break; + case WID_DOC_DIALOG_LIBRARIES: + aAny <<= m_pDocShell->GetDialogContainer(); + break; + case WID_DOC_VBA_DOCOBJ: + { + /* #i111553# This property provides the name of the constant that + will be used to store this model in the global Basic manager. + That constant will be equivalent to 'ThisComponent' but for + each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc' + constant can co-exist, as required by VBA. */ + aAny <<= OUString( "ThisWordDoc" ); + } + break; + case WID_DOC_RUNTIME_UID: + aAny <<= getRuntimeUID(); + break; + case WID_DOC_LOCK_UPDATES : + aAny <<= GetDocOrThrow().IsInReading(); + break; + case WID_DOC_BUILDID: + aAny <<= maBuildId; + break; + case WID_DOC_HAS_VALID_SIGNATURES: + aAny <<= hasValidSignatures(); + break; + case WID_DOC_INTEROP_GRAB_BAG: + getGrabBagItem(aAny); + break; + + default: + { + const SfxPoolItem& rItem = GetDocOrThrow().GetDefault(pEntry->nWID); + rItem.QueryValue(aAny, pEntry->nMemberId); + } + } + return aAny; +} + +void SwXTextDocument::addPropertyChangeListener(const OUString& /*PropertyName*/, + const Reference< XPropertyChangeListener > & /*aListener*/) +{ + OSL_FAIL("not implemented"); +} + +void SwXTextDocument::removePropertyChangeListener(const OUString& /*PropertyName*/, + const Reference< XPropertyChangeListener > & /*aListener*/) +{ + OSL_FAIL("not implemented"); +} + +void SwXTextDocument::addVetoableChangeListener(const OUString& /*PropertyName*/, + const Reference< XVetoableChangeListener > & /*aListener*/) +{ + OSL_FAIL("not implemented"); +} + +void SwXTextDocument::removeVetoableChangeListener(const OUString& /*PropertyName*/, + const Reference< XVetoableChangeListener > & /*aListener*/) +{ + OSL_FAIL("not implemented"); +} + +Reference< XNameAccess > SwXTextDocument::getLinks() +{ + if(!mxLinkTargetSupplier.is()) + { + mxLinkTargetSupplier = new SwXLinkTargetSupplier(*this); + } + return mxLinkTargetSupplier; +} + +Reference< XEnumerationAccess > SwXTextDocument::getRedlines( ) +{ + if(!mxXRedlines.is()) + { + mxXRedlines = new SwXRedlines(m_pDocShell->GetDoc()); + } + return mxXRedlines; +} + +void SwXTextDocument::NotifyRefreshListeners() +{ + // why does SwBaseShell not just call refresh? maybe because it's rSh is + // (sometimes) a different shell than GetWrtShell()? + lang::EventObject const ev(static_cast<SwXTextDocumentBaseClass &>(*this)); + std::unique_lock aGuard(m_pImpl->m_Mutex); + m_pImpl->m_RefreshListeners.notifyEach(aGuard, + & util::XRefreshListener::refreshed, ev); +} + +void SwXTextDocument::refresh() +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwViewShell *pViewShell = m_pDocShell->GetWrtShell(); + NotifyRefreshListeners(); + if(pViewShell) + pViewShell->Reformat(); +} + +void SAL_CALL SwXTextDocument::addRefreshListener( + const Reference<util::XRefreshListener> & xListener) +{ + if (xListener) + { + std::unique_lock aGuard(m_pImpl->m_Mutex); + m_pImpl->m_RefreshListeners.addInterface(aGuard, xListener); + } +} + +void SAL_CALL SwXTextDocument::removeRefreshListener( + const Reference<util::XRefreshListener> & xListener) +{ + if (xListener) + { + std::unique_lock aGuard(m_pImpl->m_Mutex); + m_pImpl->m_RefreshListeners.removeInterface(aGuard, xListener); + } +} + +void SwXTextDocument::updateLinks( ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + SwDoc& rDoc = GetDocOrThrow(); + sfx2::LinkManager& rLnkMan = rDoc.getIDocumentLinksAdministration().GetLinkManager(); + if( !rLnkMan.GetLinks().empty() ) + { + UnoActionContext aAction(&rDoc); + rLnkMan.UpdateAllLinks( false, true, nullptr ); + } +} + +//XPropertyState +PropertyState SAL_CALL SwXTextDocument::getPropertyState( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + return PropertyState_DIRECT_VALUE; +} + +Sequence< PropertyState > SAL_CALL SwXTextDocument::getPropertyStates( const Sequence< OUString >& rPropertyNames ) +{ + const sal_Int32 nCount = rPropertyNames.getLength(); + Sequence < PropertyState > aRet ( nCount ); + + std::transform(rPropertyNames.begin(), rPropertyNames.end(), aRet.getArray(), + [this](const OUString& rName) -> PropertyState { return getPropertyState(rName); }); + + return aRet; +} + +void SAL_CALL SwXTextDocument::setPropertyToDefault( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + switch(pEntry->nWID) + { + case 0:default:break; + } +} + +Any SAL_CALL SwXTextDocument::getPropertyDefault( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName); + if(!pEntry) + throw UnknownPropertyException(rPropertyName); + Any aAny; + switch(pEntry->nWID) + { + case 0:default:break; + } + return aAny; +} + +static VclPtr< OutputDevice > lcl_GetOutputDevice( const SwPrintUIOptions &rPrintUIOptions ) +{ + VclPtr< OutputDevice > pOut; + + uno::Any aAny( rPrintUIOptions.getValue( "RenderDevice" )); + uno::Reference< awt::XDevice > xRenderDevice; + aAny >>= xRenderDevice; + if (xRenderDevice.is()) + { + VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>( xRenderDevice.get() ); + pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >(); + } + + return pOut; +} + +static bool lcl_SeqHasProperty( + const uno::Sequence< beans::PropertyValue >& rOptions, + const char *pPropName ) +{ + return std::any_of(rOptions.begin(), rOptions.end(), + [&pPropName](const beans::PropertyValue& rProp) { + return rProp.Name.equalsAscii( pPropName ); }); +} + +static bool lcl_GetBoolProperty( + const uno::Sequence< beans::PropertyValue >& rOptions, + const char *pPropName ) +{ + bool bRes = false; + auto pOption = std::find_if(rOptions.begin(), rOptions.end(), + [&pPropName](const beans::PropertyValue& rProp) { + return rProp.Name.equalsAscii( pPropName ); }); + if (pOption != rOptions.end()) + pOption->Value >>= bRes; + return bRes; +} + +SfxViewShell * SwXTextDocument::GetRenderView( + bool &rbIsSwSrcView, + const uno::Sequence< beans::PropertyValue >& rOptions, + bool bIsPDFExport ) +{ + // get view shell to use + SfxViewShell *pView = nullptr; + if (bIsPDFExport) + pView = GuessViewShell( rbIsSwSrcView ); + else + { + uno::Any aTmp; + auto pOption = std::find_if(rOptions.begin(), rOptions.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "View"; }); + if (pOption != rOptions.end()) + aTmp = pOption->Value; + + uno::Reference< frame::XController > xController; + if (aTmp >>= xController) + { + OSL_ENSURE( xController.is(), "controller is empty!" ); + pView = GuessViewShell( rbIsSwSrcView, xController ); + } + } + return pView; +} + +/* + * GetRenderDoc: + * returns the document to be rendered, usually this will be the 'regular' + * document but in case of PDF export of (multi-)selection it will + * be a temporary document that gets created if not already done. + * The rpView variable will be set (if not already done) to the used + * SfxViewShell. +*/ +SwDoc * SwXTextDocument::GetRenderDoc( + SfxViewShell *&rpView, + const uno::Any& rSelection, + bool bIsPDFExport ) +{ + SwDoc *pDoc = nullptr; + + uno::Reference< frame::XModel > xModel; + rSelection >>= xModel; + if (xModel == m_pDocShell->GetModel()) + pDoc = m_pDocShell->GetDoc(); + else + { + OSL_ENSURE( !xModel.is(), "unexpected model found" ); + + if (rSelection.hasValue()) // is anything selected ? + { + // this part should only be called when a temporary document needs to be created, + // for example for PDF export or printing of (multi-)selection only. + + if (!rpView) + { + bool bIsSwSrcView = false; + // aside from maybe PDF export the view should always have been provided! + OSL_ENSURE( bIsPDFExport, "view is missing, guessing one..." ); + + rpView = GuessViewShell( bIsSwSrcView ); + } + OSL_ENSURE( rpView, "SwViewShell missing" ); + // the view shell should be SwView for documents PDF export. + // for the page preview no selection should be possible + // (the export dialog does not allow for this option) + if (auto pSwView = dynamic_cast<SwView *>( rpView )) + { + if (!m_pRenderData) + { + OSL_FAIL("GetRenderDoc: no renderdata"); + return nullptr; + } + SfxObjectShellLock xDocSh(m_pRenderData->GetTempDocShell()); + if (!xDocSh.Is()) + { + xDocSh = pSwView->CreateTmpSelectionDoc(); + m_pRenderData->SetTempDocShell(xDocSh); + } + if (xDocSh.Is()) + { + pDoc = static_cast<SwDocShell*>(&xDocSh)->GetDoc(); + rpView = pDoc->GetDocShell()->GetView(); + } + } + else + { + OSL_FAIL("unexpected SwViewShell" ); + } + } + } + return pDoc; +} + +static void lcl_SavePrintUIOptionsToDocumentPrintData( + SwDoc &rDoc, + const SwPrintUIOptions &rPrintUIOptions, + bool bIsPDFEXport ) +{ + SwPrintData aDocPrintData( rDoc.getIDocumentDeviceAccess().getPrintData() ); + + aDocPrintData.SetPrintGraphic( rPrintUIOptions.IsPrintGraphics() ); + aDocPrintData.SetPrintTable( true ); // for now it was decided that tables should always be printed + aDocPrintData.SetPrintDraw( rPrintUIOptions.IsPrintDrawings() ); + aDocPrintData.SetPrintControl( rPrintUIOptions.IsPrintFormControls() ); + aDocPrintData.SetPrintLeftPage( rPrintUIOptions.IsPrintLeftPages() ); + aDocPrintData.SetPrintRightPage( rPrintUIOptions.IsPrintRightPages() ); + aDocPrintData.SetPrintReverse( false ); /*handled by print dialog now*/ + aDocPrintData.SetPaperFromSetup( rPrintUIOptions.IsPaperFromSetup() ); + aDocPrintData.SetPrintEmptyPages( rPrintUIOptions.IsPrintEmptyPages( bIsPDFEXport ) ); + aDocPrintData.SetPrintPostIts( rPrintUIOptions.GetPrintPostItsType() ); + aDocPrintData.SetPrintProspect( rPrintUIOptions.IsPrintProspect() ); + aDocPrintData.SetPrintProspect_RTL( rPrintUIOptions.IsPrintProspectRTL() ); + aDocPrintData.SetPrintPageBackground( rPrintUIOptions.IsPrintPageBackground() ); + aDocPrintData.SetPrintBlackFont( rPrintUIOptions.IsPrintWithBlackTextColor() ); + // aDocPrintData.SetPrintSingleJobs( b ); handled by File/Print dialog itself + // arDocPrintData.SetFaxName( s ); n/a in File/Print dialog + aDocPrintData.SetPrintHiddenText( rPrintUIOptions.IsPrintHiddenText() ); + aDocPrintData.SetPrintTextPlaceholder( rPrintUIOptions.IsPrintTextPlaceholders() ); + + rDoc.getIDocumentDeviceAccess().setPrintData( aDocPrintData ); +} + +sal_Int32 SAL_CALL SwXTextDocument::getRendererCount( + const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& rxOptions ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + { + throw DisposedException( OUString(), + static_cast< XTextDocument* >(this) ); + } + + const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ); + bool bIsSwSrcView = false; + SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); + + if (!bIsSwSrcView && !m_pRenderData) + m_pRenderData.reset(new SwRenderData); + if (!m_pPrintUIOptions) + m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView ); + bool bFormat = m_pPrintUIOptions->processPropertiesAndCheckFormat( rxOptions ); + + SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); + OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); + if (!pDoc || !pView) + return 0; + + // save current UI options from the print dialog for the next call to that dialog + lcl_SavePrintUIOptionsToDocumentPrintData( *pDoc, *m_pPrintUIOptions, bIsPDFExport ); + + sal_Int32 nRet = 0; + if (bIsSwSrcView) + { + SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView); + VclPtr< OutputDevice> pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); + nRet = rSwSrcView.PrintSource( pOutDev, 1 /* dummy */, true /* get page count only */ ); + } + else + { + SwDocShell *pRenderDocShell = pDoc->GetDocShell(); + + // TODO/mba: we really need a generic way to get the SwViewShell! + SwViewShell* pViewShell = nullptr; + SwView* pSwView = dynamic_cast<SwView*>( pView ); + if ( pSwView ) + { + pViewShell = pSwView->GetWrtShellPtr(); + } + else + { + if ( bIsPDFExport && bFormat ) + { + //create a hidden view to be able to export as PDF also in print preview + //pView and pSwView are not changed intentionally! + m_pHiddenViewFrame = SfxViewFrame::LoadHiddenDocument( *pRenderDocShell, SFX_INTERFACE_SFXDOCSH ); + pViewShell = static_cast<SwView*>(m_pHiddenViewFrame->GetViewShell())->GetWrtShellPtr(); + } + else + pViewShell = static_cast<SwPagePreview*>(pView)->GetViewShell(); + } + + if (!pViewShell || !pViewShell->GetLayout()) + return 0; + + if (bFormat) + { + // #i38289 + if( pViewShell->GetViewOptions()->getBrowseMode() || + pViewShell->GetViewOptions()->IsWhitespaceHidden() ) + { + SwViewOption aOpt( *pViewShell->GetViewOptions() ); + aOpt.setBrowseMode( false ); + aOpt.SetHideWhitespaceMode( false ); + pViewShell->ApplyViewOptions( aOpt ); + if (pSwView) + { + pSwView->RecheckBrowseMode(); + } + } + + // reformatting the document for printing will show the changes in the view + // which is likely to produce many unwanted and not nice to view actions. + // We don't want that! Thus we disable updating of the view. + pViewShell->StartAction(); + + if (pSwView) + { + if (m_pRenderData && m_pRenderData->NeedNewViewOptionAdjust( *pViewShell ) ) + m_pRenderData->ViewOptionAdjustStop(); + if (m_pRenderData && !m_pRenderData->IsViewOptionAdjust()) + { + m_pRenderData->ViewOptionAdjustStart( + *pViewShell, *pViewShell->GetViewOptions() ); + } + } + + m_pRenderData->MakeSwPrtOptions( pRenderDocShell, + m_pPrintUIOptions.get(), bIsPDFExport ); + + if (pSwView) + { + // PDF export should not make use of the SwPrtOptions + const SwPrintData *pPrtOptions = bIsPDFExport + ? nullptr : m_pRenderData->GetSwPrtOptions(); + bool setShowPlaceHoldersInPDF = false; + if(bIsPDFExport) + setShowPlaceHoldersInPDF = lcl_GetBoolProperty( rxOptions, "ExportPlaceholders" ); + m_pRenderData->ViewOptionAdjust( pPrtOptions, setShowPlaceHoldersInPDF ); + } + + // since printing now also use the API for PDF export this option + // should be set for printing as well ... + pViewShell->SetPDFExportOption( true ); + + // there is some redundancy between those two function calls, but right now + // there is no time to sort this out. + //TODO: check what exactly needs to be done and make just one function for that + pViewShell->CalcLayout(); + + // #122919# Force field update before PDF export, but after layout init (tdf#121962) + bool bStateChanged = false; + // check configuration: shall update of printing information in DocInfo set the document to "modified"? + if (pRenderDocShell->IsEnableSetModified() && !utl::ConfigManager::IsFuzzing() && !officecfg::Office::Common::Print::PrintingModifiesDocument::get()) + { + pRenderDocShell->EnableSetModified( false ); + bStateChanged = true; + } + pViewShell->SwViewShell::UpdateFields(true); + if( bStateChanged ) + pRenderDocShell->EnableSetModified(); + + pViewShell->CalcPagesForPrint( pViewShell->GetPageCount() ); + + pViewShell->SetPDFExportOption( false ); + + // enable view again + pViewShell->EndAction(); + } + + const sal_Int32 nPageCount = pViewShell->GetPageCount(); + + // get number of pages to be rendered + + const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); + if (bPrintProspect) + { + SwDoc::CalculatePagePairsForProspectPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, nPageCount ); + nRet = m_pRenderData->GetPagePairsForProspectPrinting().size(); + } + else + { + const SwPostItMode nPostItMode = static_cast<SwPostItMode>( m_pPrintUIOptions->getIntValue( "PrintAnnotationMode", 0 ) ); + if (nPostItMode != SwPostItMode::NONE) + { + VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); + m_pRenderData->CreatePostItData(*pDoc, pViewShell->GetViewOptions(), pOutDev); + } + + // get set of valid document pages (according to the current settings) + // and their start frames + SwDoc::CalculatePagesForPrinting( *pViewShell->GetLayout(), *m_pRenderData, *m_pPrintUIOptions, bIsPDFExport, nPageCount ); + + if (nPostItMode != SwPostItMode::NONE) + { + SwDoc::UpdatePagesForPrintingWithPostItData( *m_pRenderData, + *m_pPrintUIOptions, nPageCount ); + } + + nRet = m_pRenderData->GetPagesToPrint().size(); + } + } + OSL_ENSURE( nRet >= 0, "negative number of pages???" ); + // tdf#144989 the layout is complete now - prevent DoIdleJobs() from + // messing it up, particulary SwDocUpdateField::MakeFieldList_() unhiding + // sections + pDoc->getIDocumentTimerAccess().BlockIdling(); + + return nRet; +} + +uno::Sequence< beans::PropertyValue > SAL_CALL SwXTextDocument::getRenderer( + sal_Int32 nRenderer, + const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& rxOptions ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + { + throw DisposedException("", static_cast< XTextDocument* >(this)); + } + + const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ); + bool bIsSwSrcView = false; + SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); + + // m_pRenderData should NOT be created here! + // That should only be done in getRendererCount. If this function is called before + // getRendererCount was called then the caller will probably just retrieve the extra UI options + // and is not interested in getting valid information about the other data that would + // otherwise be provided here! +// if( ! m_pRenderData ) +// m_pRenderData = new SwRenderData; + if (!m_pPrintUIOptions) + m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView ); + m_pPrintUIOptions->processProperties( rxOptions ); + const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); + const bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport ); + const bool bPrintPaperFromSetup = m_pPrintUIOptions->getBoolValue( "PrintPaperFromSetup" ); + + SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); + OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); + if (!pDoc || !pView) + return uno::Sequence< beans::PropertyValue >(); + + // due to #110067# (document page count changes sometimes during + // PDF export/printing) we can not check for the upper bound properly. + // Thus instead of throwing the exception we silently return. + if (0 > nRenderer) + throw IllegalArgumentException(); + + sal_Int32 nMaxRenderer = 0; + if (!bIsSwSrcView && m_pRenderData) + { + OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" ); + nMaxRenderer = bPrintProspect? + m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 : + m_pRenderData->GetPagesToPrint().size() - 1; + } + // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print + // we obmit checking of the upper bound in this case. + if (!bIsSwSrcView && m_pRenderData && nRenderer > nMaxRenderer) + return uno::Sequence< beans::PropertyValue >(); + + uno::Sequence< beans::PropertyValue > aRenderer; + if (m_pRenderData) + { + // #i114210# + // determine the correct page number from the renderer index + // #i114875 + // consider brochure print + const sal_Int32 nPage = bPrintProspect + ? nRenderer + 1 + : m_pRenderData->GetPagesToPrint()[ nRenderer ]; + + // get paper tray to use ... + sal_Int32 nPrinterPaperTray = -1; + if (! bPrintPaperFromSetup) + { + // ... from individual page style (see the page tab in Format/Page dialog) + const std::map< sal_Int32, sal_Int32 > &rPaperTrays = m_pRenderData->GetPrinterPaperTrays(); + std::map< sal_Int32, sal_Int32 >::const_iterator aIt( rPaperTrays.find( nPage ) ); + if (aIt != rPaperTrays.end()) + nPrinterPaperTray = aIt->second; + } + + awt::Size aPageSize; + awt::Point aPagePos; + awt::Size aPreferredPageSize; + Size aTmpSize; + if (bIsSwSrcView || bPrintProspect) + { + // for printing of HTML source code and prospect printing we should use + // the printers paper size since + // a) HTML source view has no page size + // b) prospect printing has a different page size from the documents page + // since two document pages will get rendered on one printer page + + // since PageIncludesNonprintableArea will be set to true we can return the + // printers paper size here. + // Sometimes 'getRenderer' is only called to get "ExtraPrintUIOptions", in this + // case we won't get an OutputDevice here, but then the caller also has no need + // for the correct PageSize right now... + VclPtr< Printer > pPrinter = dynamic_cast< Printer * >(lcl_GetOutputDevice( *m_pPrintUIOptions ).get()); + if (pPrinter) + { + // HTML source view and prospect adapt to the printer's paper size + aTmpSize = pPrinter->GetPaperSize(); + aTmpSize = OutputDevice::LogicToLogic( aTmpSize, + pPrinter->GetMapMode(), MapMode( MapUnit::Map100thMM )); + aPageSize = awt::Size( aTmpSize.Width(), aTmpSize.Height() ); + #if 0 + // #i115048# it seems users didn't like getting double the formatted page size + // revert to "old" behavior scaling to the current paper size of the printer + if (bPrintProspect) + { + // we just state what output size we would need + // which may cause vcl to set that page size on the printer + // (if available and not overridden by the user) + aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages ); + aPreferredPageSize = awt::Size ( convertTwipToMm100( 2 * aTmpSize.Width() ), + convertTwipToMm100( aTmpSize.Height() )); + } + #else + if( bPrintProspect ) + { + // just switch to an appropriate portrait/landscape format + // FIXME: brochure printing with landscape pages puts the + // pages next to each other, so landscape is currently always + // the better choice + if( aPageSize.Width < aPageSize.Height ) + { + aPreferredPageSize.Width = aPageSize.Height; + aPreferredPageSize.Height = aPageSize.Width; + } + } + #endif + } + } + else + { + // TODO/mba: we really need a generic way to get the SwViewShell! + SwViewShell* pVwSh = nullptr; + SwView* pSwView = dynamic_cast<SwView*>( pView ); + if ( pSwView ) + pVwSh = pSwView->GetWrtShellPtr(); + else + pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell(); + + if (pVwSh) + { + aTmpSize = pVwSh->GetPageSize( nPage, bIsSkipEmptyPages ); + aPageSize = awt::Size ( convertTwipToMm100( aTmpSize.Width() ), + convertTwipToMm100( aTmpSize.Height() )); + Point aPoint = pVwSh->GetPagePos(nPage); + aPagePos = awt::Point(convertTwipToMm100(aPoint.X()), convertTwipToMm100(aPoint.Y())); + } + } + + sal_Int32 nLen = 3; + aRenderer = { comphelper::makePropertyValue("PageSize", aPageSize), + comphelper::makePropertyValue("PageIncludesNonprintableArea", true), + comphelper::makePropertyValue("PagePos", aPagePos) }; + if (aPreferredPageSize.Width && aPreferredPageSize.Height) + { + ++nLen; + aRenderer.realloc( nLen ); + auto pRenderer = aRenderer.getArray(); + pRenderer[ nLen - 1 ].Name = "PreferredPageSize"; + pRenderer[ nLen - 1 ].Value <<= aPreferredPageSize; + } + if (nPrinterPaperTray >= 0) + { + ++nLen; + aRenderer.realloc( nLen ); + auto pRenderer = aRenderer.getArray(); + pRenderer[ nLen - 1 ].Name = "PrinterPaperTray"; + pRenderer[ nLen - 1 ].Value <<= nPrinterPaperTray; + } + } + + // #i117783# + if ( m_bApplyPagePrintSettingsFromXPagePrintable ) + { + SwDoc& rDoc = GetDocOrThrow(); + const SwPagePreviewPrtData* pPagePrintSettings = rDoc.GetPreviewPrtData(); + if ( pPagePrintSettings && + ( pPagePrintSettings->GetRow() > 1 || + pPagePrintSettings->GetCol() > 1 ) ) + { + // extend render data by page print settings attributes + sal_Int32 nLen = aRenderer.getLength(); + const sal_Int32 nRenderDataIdxStart = nLen; + nLen += 9; + aRenderer.realloc( nLen ); + auto pRenderer = aRenderer.getArray(); + // put page print settings attribute into render data + const sal_Int32 nRow = pPagePrintSettings->GetRow(); + pRenderer[ nRenderDataIdxStart + 0 ].Name = "NUpRows"; + pRenderer[ nRenderDataIdxStart + 0 ].Value <<= std::max<sal_Int32>( nRow, 1); + const sal_Int32 nCol = pPagePrintSettings->GetCol(); + pRenderer[ nRenderDataIdxStart + 1 ].Name = "NUpColumns"; + pRenderer[ nRenderDataIdxStart + 1 ].Value <<= std::max<sal_Int32>( nCol, 1); + pRenderer[ nRenderDataIdxStart + 2 ].Name = "NUpPageMarginLeft"; + pRenderer[ nRenderDataIdxStart + 2 ].Value <<= pPagePrintSettings->GetLeftSpace(); + pRenderer[ nRenderDataIdxStart + 3 ].Name = "NUpPageMarginRight"; + pRenderer[ nRenderDataIdxStart + 3 ].Value <<= pPagePrintSettings->GetRightSpace(); + pRenderer[ nRenderDataIdxStart + 4 ].Name = "NUpPageMarginTop"; + pRenderer[ nRenderDataIdxStart + 4 ].Value <<= pPagePrintSettings->GetTopSpace(); + pRenderer[ nRenderDataIdxStart + 5 ].Name = "NUpPageMarginBottom"; + pRenderer[ nRenderDataIdxStart + 5 ].Value <<= pPagePrintSettings->GetBottomSpace(); + pRenderer[ nRenderDataIdxStart + 6 ].Name = "NUpHorizontalSpacing"; + pRenderer[ nRenderDataIdxStart + 6 ].Value <<= pPagePrintSettings->GetHorzSpace(); + pRenderer[ nRenderDataIdxStart + 7 ].Name = "NUpVerticalSpacing"; + pRenderer[ nRenderDataIdxStart + 7 ].Value <<= pPagePrintSettings->GetVertSpace(); + if (Printer* pPrinter = rDoc.getIDocumentDeviceAccess().getPrinter(false)) + { + awt::Size aNewPageSize; + const Size aPageSize = pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM ) ); + aNewPageSize = awt::Size( aPageSize.Width(), aPageSize.Height() ); + if ( ( pPagePrintSettings->GetLandscape() && + aPageSize.Width() < aPageSize.Height() ) || + ( !pPagePrintSettings->GetLandscape() && + aPageSize.Width() > aPageSize.Height() ) ) + { + aNewPageSize = awt::Size( aPageSize.Height(), aPageSize.Width() ); + } + pRenderer[ nRenderDataIdxStart + 8 ].Name = "NUpPaperSize"; + pRenderer[ nRenderDataIdxStart + 8 ].Value <<= aNewPageSize; + } + } + + m_bApplyPagePrintSettingsFromXPagePrintable = false; + } + + m_pPrintUIOptions->appendPrintUIOptions( aRenderer ); + + return aRenderer; +} + +SfxViewShell * SwXTextDocument::GuessViewShell( + /* out */ bool &rbIsSwSrcView, + const uno::Reference< css::frame::XController >& rController ) +{ + // #130810# SfxViewShell::Current() / SfxViewShell::GetObjectShell() + // must not be used (see comment from MBA) + + SfxViewShell *pView = nullptr; + SwView *pSwView = nullptr; + SwPagePreview *pSwPagePreview = nullptr; + SwSrcView *pSwSrcView = nullptr; + SfxViewFrame *pFrame = SfxViewFrame::GetFirst( m_pDocShell, false ); + + // look for the view shell with the same controller in use, + // otherwise look for a suitable view, preferably a SwView, + // if that one is not found use a SwPagePreview if found. + while (pFrame) + { + pView = pFrame->GetViewShell(); + pSwView = dynamic_cast< SwView * >(pView); + pSwSrcView = dynamic_cast< SwSrcView * >(pView); + if (!pSwPagePreview) + pSwPagePreview = dynamic_cast< SwPagePreview * >(pView); + if (rController.is()) + { + if (pView && pView->GetController() == rController) + break; + } + else if (pSwView || pSwSrcView) + break; + pFrame = SfxViewFrame::GetNext( *pFrame, m_pDocShell, false ); + } + + OSL_ENSURE( pSwView || pSwPagePreview || pSwSrcView, "failed to get view shell" ); + if (pView) + rbIsSwSrcView = pSwSrcView != nullptr; + return pView; +} + +void SAL_CALL SwXTextDocument::render( + sal_Int32 nRenderer, + const uno::Any& rSelection, + const uno::Sequence< beans::PropertyValue >& rxOptions ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + { + throw DisposedException( OUString(), + static_cast< XTextDocument* >(this) ); + } + + // due to #110067# (document page count changes sometimes during + // PDF export/printing) we can not check for the upper bound properly. + // Thus instead of throwing the exception we silently return. + if (0 > nRenderer) + throw IllegalArgumentException(); + + // tdf#135244: prevent jumping to cursor at any temporary modification + auto aLock = m_pDocShell->LockAllViews(); + + const bool bHasPDFExtOutDevData = lcl_SeqHasProperty( rxOptions, "HasPDFExtOutDevData" ); + const bool bIsPDFExport = !lcl_SeqHasProperty( rxOptions, "IsPrinter" ) || bHasPDFExtOutDevData; + bool bIsSwSrcView = false; + SfxViewShell *pView = GetRenderView( bIsSwSrcView, rxOptions, bIsPDFExport ); + + OSL_ENSURE( m_pRenderData, "data should have been created already in getRendererCount..." ); + OSL_ENSURE( m_pPrintUIOptions, "data should have been created already in getRendererCount..." ); + if (!bIsSwSrcView && !m_pRenderData) + m_pRenderData.reset(new SwRenderData); + if (!m_pPrintUIOptions) + m_pPrintUIOptions = lcl_GetPrintUIOptions( m_pDocShell, pView ); + m_pPrintUIOptions->processProperties( rxOptions ); + const bool bPrintProspect = m_pPrintUIOptions->getBoolValue( "PrintProspect" ); + const bool bLastPage = m_pPrintUIOptions->getBoolValue( "IsLastPage" ); + + SwDoc *pDoc = GetRenderDoc( pView, rSelection, bIsPDFExport ); + OSL_ENSURE( pDoc && pView, "doc or view shell missing!" ); + if (pDoc && pView) + { + sal_Int32 nMaxRenderer = 0; + if (!bIsSwSrcView) + { + OSL_ENSURE( m_pRenderData, "m_pRenderData missing!!" ); + nMaxRenderer = bPrintProspect? + m_pRenderData->GetPagePairsForProspectPrinting().size() - 1 : + m_pRenderData->GetPagesToPrint().size() - 1; + } + // since SwSrcView::PrintSource is a poor implementation to get the number of pages to print + // we obmit checking of the upper bound in this case. + if (bIsSwSrcView || nRenderer <= nMaxRenderer) + { + if (bIsSwSrcView) + { + SwSrcView& rSwSrcView = dynamic_cast<SwSrcView&>(*pView); + VclPtr< OutputDevice > pOutDev = lcl_GetOutputDevice( *m_pPrintUIOptions ); + rSwSrcView.PrintSource(pOutDev, nRenderer + 1, false); + } + else + { + // the view shell should be SwView for documents PDF export + // or SwPagePreview for PDF export of the page preview + SwViewShell* pVwSh = nullptr; + // TODO/mba: we really need a generic way to get the SwViewShell! + const SwView* pSwView = dynamic_cast<const SwView*>(pView); + if (pSwView) + pVwSh = pSwView->GetWrtShellPtr(); + else + pVwSh = static_cast<SwPagePreview*>(pView)->GetViewShell(); + + // get output device to use + VclPtr< OutputDevice > pOut = lcl_GetOutputDevice( *m_pPrintUIOptions ); + + if(pVwSh && pOut && m_pRenderData->HasSwPrtOptions()) + { + const OUString aPageRange = m_pPrintUIOptions->getStringValue( "PageRange" ); + const bool bFirstPage = m_pPrintUIOptions->getBoolValue( "IsFirstPage" ); + bool bIsSkipEmptyPages = !m_pPrintUIOptions->IsPrintEmptyPages( bIsPDFExport ); + + OSL_ENSURE((pSwView && m_pRenderData->IsViewOptionAdjust()) + || (!pSwView && !m_pRenderData->IsViewOptionAdjust()), + "SwView / SwViewOptionAdjust_Impl availability mismatch" ); + + // since printing now also use the API for PDF export this option + // should be set for printing as well ... + pVwSh->SetPDFExportOption( true ); + + // #i12836# enhanced pdf export + + // First, we have to export hyperlinks, notes, and outline to pdf. + // During this process, additional information required for tagging + // the pdf file are collected, which are evaluated during painting. + + SwWrtShell* pWrtShell = pSwView ? pSwView->GetWrtShellPtr() : nullptr; + + SwPrintData rSwPrtOptions = *m_pRenderData->GetSwPrtOptions(); + if (bIsPDFExport) + { + rSwPrtOptions.SetPrintPostIts( + lcl_GetBoolProperty(rxOptions, "ExportNotesInMargin") + ? SwPostItMode::InMargins + : SwPostItMode::NONE); + } + + if (bIsPDFExport && (bFirstPage || bHasPDFExtOutDevData) && pWrtShell) + { + SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, false, rSwPrtOptions ); + } + + if (bPrintProspect) + pVwSh->PrintProspect( pOut, rSwPrtOptions, nRenderer ); + else // normal printing and PDF export + pVwSh->PrintOrPDFExport( pOut, rSwPrtOptions, nRenderer, bIsPDFExport ); + + // #i35176# + + // After printing the last page, we take care for the links coming + // from the EditEngine. The links are generated during the painting + // process, but the destinations are still missing. + + if (bIsPDFExport && bLastPage && pWrtShell) + { + SwEnhancedPDFExportHelper aHelper( *pWrtShell, *pOut, aPageRange, bIsSkipEmptyPages, true, rSwPrtOptions ); + } + + pVwSh->SetPDFExportOption( false ); + + // last page to be rendered? (not necessarily the last page of the document) + // -> do clean-up of data + if (bLastPage) + { + // #i96167# haggai: delete ViewOptionsAdjust here because it makes use + // of the shell, which might get destroyed in lcl_DisposeView! + if (m_pRenderData->IsViewOptionAdjust()) + m_pRenderData->ViewOptionAdjustStop(); + + if (m_pRenderData->HasPostItData()) + m_pRenderData->DeletePostItData(); + if (m_pHiddenViewFrame) + { + lcl_DisposeView( m_pHiddenViewFrame, m_pDocShell ); + m_pHiddenViewFrame = nullptr; + + // prevent crash described in #i108805 + SwDocShell *pRenderDocShell = pDoc->GetDocShell(); + pRenderDocShell->GetMedium()->GetItemSet().Put( SfxBoolItem( SID_HIDDEN, false ) ); + + } + } + } + } + } + } + if( bLastPage ) + { + // tdf#144989 enable DoIdleJobs() again after last page + pDoc->getIDocumentTimerAccess().UnblockIdling(); + m_pRenderData.reset(); + m_pPrintUIOptions.reset(); + } +} + +// xforms::XFormsSupplier +Reference<XNameContainer> SAL_CALL SwXTextDocument::getXForms() +{ + SolarMutexGuard aGuard; + if ( !m_pDocShell ) + throw DisposedException( OUString(), static_cast< XTextDocument* >( this ) ); + return GetDocOrThrow().getXForms(); +} + +uno::Reference< text::XFlatParagraphIterator > SAL_CALL SwXTextDocument::getFlatParagraphIterator(::sal_Int32 nTextMarkupType, sal_Bool bAutomatic) +{ + SolarMutexGuard aGuard; + if (!IsValid()) + { + throw DisposedException("SwXTextDocument not valid", + static_cast<XTextDocument*>(this)); + } + + return SwUnoCursorHelper::CreateFlatParagraphIterator( + GetDocOrThrow(), nTextMarkupType, bAutomatic); +} + +uno::Reference< util::XCloneable > SwXTextDocument::createClone( ) +{ + SolarMutexGuard aGuard; + if(!IsValid()) + throw DisposedException("", static_cast< XTextDocument* >(this)); + + // create a new document - hidden - copy the storage and return it + // SfxObjectShellRef is used here, since the model should control object lifetime after creation + // and thus SfxObjectShellLock is not allowed here + // the model holds reference to the shell, so the shell will not destructed at the end of method + SfxObjectShellRef pShell = GetDocOrThrow().CreateCopy(false, false); + uno::Reference< frame::XModel > xNewModel = pShell->GetModel(); + uno::Reference< embed::XStorage > xNewStorage = ::comphelper::OStorageHelper::GetTemporaryStorage( ); + uno::Sequence< beans::PropertyValue > aTempMediaDescriptor; + storeToStorage( xNewStorage, aTempMediaDescriptor ); + uno::Reference< document::XStorageBasedDocument > xStorageDoc( xNewModel, uno::UNO_QUERY ); + xStorageDoc->loadFromStorage( xNewStorage, aTempMediaDescriptor ); + return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY ); +} + +void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener) +{ + SolarMutexGuard aGuard; + + if (IsValid() && xListener.is()) + m_pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener); +} + +void SwXTextDocument::removePasteEventListener( + const uno::Reference<text::XPasteListener>& xListener) +{ + SolarMutexGuard aGuard; + + if (IsValid() && xListener.is()) + m_pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener); +} + +void SwXTextDocument::paintTile( VirtualDevice &rDevice, + int nOutputWidth, int nOutputHeight, + int nTilePosX, int nTilePosY, + tools::Long nTileWidth, tools::Long nTileHeight ) +{ + SwViewShell* pViewShell = m_pDocShell->GetWrtShell(); + pViewShell->PaintTile(rDevice, nOutputWidth, nOutputHeight, + nTilePosX, nTilePosY, nTileWidth, nTileHeight); + + LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight, + nTilePosX, nTilePosY, nTileWidth, nTileHeight); + + // Draw Form controls + comphelper::LibreOfficeKit::setTiledPainting(true); + SwDrawModel* pDrawLayer = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel(); + SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(0)); + SdrView* pDrawView = pViewShell->GetDrawView(); + SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin(); + tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight)); + Size aOutputSize(nOutputWidth, nOutputHeight); + LokControlHandler::paintControlTile(pPage, pDrawView, rEditWin, rDevice, aOutputSize, aTileRect); + comphelper::LibreOfficeKit::setTiledPainting(false); +} + +Size SwXTextDocument::getDocumentSize() +{ + SwViewShell* pViewShell = m_pDocShell->GetWrtShell(); + Size aDocSize = pViewShell->GetDocSize(); + + return Size(aDocSize.Width() + 2 * DOCUMENTBORDER, + aDocSize.Height() + 2 * DOCUMENTBORDER); +} + +void SwXTextDocument::setPart(int nPart, bool /*bAllowChangeFocus*/) +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (!pWrtShell) + return; + + pWrtShell->GotoPage(nPart + 1, true); +} + +int SwXTextDocument::getParts() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (!pWrtShell) + return 0; + + return pWrtShell->GetPageCnt(); +} + +OUString SwXTextDocument::getPartPageRectangles() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (!pWrtShell) + return OUString(); + + return pWrtShell->getPageRectangles(); +} + +void SwXTextDocument::setClipboard(const uno::Reference<datatransfer::clipboard::XClipboard>& xClipboard) +{ + SolarMutexGuard aGuard; + + SwView* pView = m_pDocShell->GetView(); + if (pView) + pView->GetEditWin().SetClipboard(xClipboard); +} + +bool SwXTextDocument::isMimeTypeSupported() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (!pWrtShell) + return false; + + TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&pWrtShell->GetView().GetEditWin())); + if (SdrView* pSdrView = pWrtShell->GetDrawView()) + { + if (pSdrView->GetTextEditObject()) + // Editing shape text + return EditEngine::HasValidData(aDataHelper.GetTransferable()); + } + + return aDataHelper.GetXTransferable().is() && SwTransferable::IsPaste(*pWrtShell, aDataHelper); +} + +void SwXTextDocument::setClientVisibleArea(const tools::Rectangle& rRectangle) +{ + if (SwView* pView = m_pDocShell->GetView()) + { + // set the PgUp/PgDown offset + pView->ForcePageUpDownOffset(2 * rRectangle.GetHeight() / 3); + } + + if (SwViewShell* pViewShell = m_pDocShell->GetWrtShell()) + { + pViewShell->setLOKVisibleArea(rRectangle); + } +} + +void SwXTextDocument::setClientZoom(int nTilePixelWidth_, int /*nTilePixelHeight_*/, + int nTileTwipWidth_, int /*nTileTwipHeight_*/) +{ + // Here we set the zoom value as it has been set by the user in the client. + // This value is used in postMouseEvent and setGraphicSelection methods + // for in place chart editing. We assume that x and y scale is roughly + // the same. + SfxInPlaceClient* pIPClient = m_pDocShell->GetView()->GetIPClient(); + if (!pIPClient) + return; + + SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell(); + double fScale = 100.0 * nTilePixelWidth_ / nTileTwipWidth_ + * o3tl::convert(1.0, o3tl::Length::px, o3tl::Length::twip); + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + if (aOption.GetZoom() != fScale) + { + aOption.SetZoom(fScale); + pWrtViewShell->ApplyViewOptions(aOption); + + // Changing the zoom value doesn't always trigger the updating of + // the client ole object area, so we call it directly. + pIPClient->VisAreaChanged(); + } +} + +PointerStyle SwXTextDocument::getPointer() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (!pWrtShell) + return PointerStyle::Arrow; + + return pWrtShell->GetView().GetEditWin().GetPointer(); +} + +void SwXTextDocument::getTrackedChanges(tools::JsonWriter& rJson) +{ + auto redlinesNode = rJson.startArray("redlines"); + + // Disable since usability is very low beyond some small number of changes. + static bool bDisableRedlineComments = getenv("DISABLE_REDLINE") != nullptr; + if (bDisableRedlineComments) + return; + + const SwRedlineTable& rRedlineTable + = GetDocOrThrow().getIDocumentRedlineAccess().GetRedlineTable(); + for (SwRedlineTable::size_type i = 0; i < rRedlineTable.size(); ++i) + { + auto redlineNode = rJson.startStruct(); + rJson.put("index", rRedlineTable[i]->GetId()); + rJson.put("author", rRedlineTable[i]->GetAuthorString(1)); + rJson.put("type", SwRedlineTypeToOUString( + rRedlineTable[i]->GetRedlineData().GetType())); + rJson.put("comment", + rRedlineTable[i]->GetRedlineData().GetComment()); + rJson.put("description", rRedlineTable[i]->GetDescr()); + OUString sDateTime = utl::toISO8601( + rRedlineTable[i]->GetRedlineData().GetTimeStamp().GetUNODateTime()); + rJson.put("dateTime", sDateTime); + + SwContentNode* pContentNd = rRedlineTable[i]->GetPointContentNode(); + SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current()); + if (pView && pContentNd) + { + SwShellCursor aCursor(pView->GetWrtShell(), *(rRedlineTable[i]->Start())); + aCursor.SetMark(); + aCursor.GetMark()->Assign(*pContentNd, rRedlineTable[i]->End()->GetContentIndex()); + + aCursor.FillRects(); + + SwRects* pRects(&aCursor); + std::vector<OString> aRects; + for (const SwRect& rNextRect : *pRects) + aRects.push_back(rNextRect.SVRect().toString()); + + const OString sRects = comphelper::string::join("; ", aRects); + rJson.put("textRange", sRects); + } + } +} + +void SwXTextDocument::getTrackedChangeAuthors(tools::JsonWriter& rJsonWriter) +{ + SW_MOD()->GetRedlineAuthorInfo(rJsonWriter); +} + +void SwXTextDocument::getRulerState(tools::JsonWriter& rJsonWriter) +{ + SwView* pView = m_pDocShell->GetView(); + dynamic_cast<SwCommentRuler&>(pView->GetHRuler()).CreateJsonNotification(rJsonWriter); +} + +void SwXTextDocument::getPostIts(tools::JsonWriter& rJsonWriter) +{ + SolarMutexGuard aGuard; + auto commentsNode = rJsonWriter.startArray("comments"); + for (auto const& sidebarItem : *m_pDocShell->GetView()->GetPostItMgr()) + { + sw::annotation::SwAnnotationWin* pWin = sidebarItem->mpPostIt.get(); + + if (!pWin) + { + continue; + } + + const SwPostItField* pField = pWin->GetPostItField(); + const SwRect& aRect = pWin->GetAnchorRect(); + tools::Rectangle aSVRect(aRect.Pos().getX(), + aRect.Pos().getY(), + aRect.Pos().getX() + aRect.SSize().Width(), + aRect.Pos().getY() + aRect.SSize().Height()); + + if (!sidebarItem->maLayoutInfo.mPositionFromCommentAnchor) + { + // Comments on frames: anchor position is the corner position, not the whole frame. + aSVRect.SetSize(Size(0, 0)); + } + + std::vector<OString> aRects; + for (const basegfx::B2DRange& aRange : pWin->GetAnnotationTextRanges()) + { + const SwRect rect(aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), aRange.getHeight()); + aRects.push_back(rect.SVRect().toString()); + } + const OString sRects = comphelper::string::join("; ", aRects); + + auto commentNode = rJsonWriter.startStruct(); + rJsonWriter.put("id", pField->GetPostItId()); + rJsonWriter.put("parentId", pField->GetParentPostItId()); + rJsonWriter.put("author", pField->GetPar1()); + rJsonWriter.put("text", pField->GetPar2()); + rJsonWriter.put("resolved", pField->GetResolved() ? "true" : "false"); + rJsonWriter.put("dateTime", utl::toISO8601(pField->GetDateTime().GetUNODateTime())); + rJsonWriter.put("anchorPos", aSVRect.toString()); + rJsonWriter.put("textRange", sRects); + } +} + +void SwXTextDocument::executeFromFieldEvent(const StringMap& aArguments) +{ + auto aIter = aArguments.find("type"); + if (aIter == aArguments.end() || aIter->second != "drop-down") + return; + + aIter = aArguments.find("cmd"); + if (aIter == aArguments.end() || aIter->second != "selected") + return; + + aIter = aArguments.find("data"); + if (aIter == aArguments.end()) + return; + + sal_Int32 nSelection = aIter->second.toInt32(); + SwPosition aPos(*m_pDocShell->GetWrtShell()->GetCursor()->GetPoint()); + sw::mark::IFieldmark* pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos); + if ( !pFieldBM ) + { + aPos.AdjustContent(-1); + pFieldBM = m_pDocShell->GetWrtShell()->getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos); + } + if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN) + { + if (nSelection >= 0) + { + (*pFieldBM->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= nSelection; + pFieldBM->Invalidate(); + m_pDocShell->GetWrtShell()->SetModified(); + m_pDocShell->GetView()->GetEditWin().LogicInvalidate(nullptr); + } + } +} + +std::vector<basegfx::B2DRange> +SwXTextDocument::getSearchResultRectangles(const char* pPayload) +{ + SwDoc* pDoc = m_pDocShell->GetDoc(); + if (!pDoc) + return std::vector<basegfx::B2DRange>(); + + sw::search::SearchResultLocator aLocator(pDoc); + sw::search::LocationResult aResult = aLocator.findForPayload(pPayload); + if (aResult.mbFound) + { + return aResult.maRectangles; + } + return std::vector<basegfx::B2DRange>(); +} + +OString SwXTextDocument::getViewRenderState(SfxViewShell* pViewShell) +{ + OStringBuffer aState; + SwView* pView = pViewShell ? dynamic_cast<SwView*>(pViewShell) : m_pDocShell->GetView(); + if (pView && pView->GetWrtShellPtr()) + { + const SwViewOption* pVOpt = pView->GetWrtShell().GetViewOptions(); + if (pVOpt) + { + if (pVOpt->IsViewMetaChars()) + aState.append('P'); + if (pVOpt->IsOnlineSpell()) + aState.append('S'); + aState.append(';'); + + OString aThemeName = OUStringToOString(pVOpt->GetThemeName(), RTL_TEXTENCODING_UTF8); + aState.append(aThemeName); + } + } + return aState.makeStringAndClear(); +} + +namespace +{ +inline constexpr OUString SELECTED_DATE_FORMAT = u"YYYY-MM-DD"_ustr; +} + +void SwXTextDocument::executeContentControlEvent(const StringMap& rArguments) +{ + auto it = rArguments.find("type"); + if (it == rArguments.end()) + { + return; + } + + if (it->second == "drop-down") + { + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + const SwPosition* pStart = pWrtShell->GetCursor()->Start(); + SwTextNode* pTextNode = pStart->GetNode().GetTextNode(); + if (!pTextNode) + { + return; + } + + SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(), + RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); + if (!pAttr) + { + return; + } + + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl(); + std::shared_ptr<SwContentControl> pContentControl = rFormatContentControl.GetContentControl(); + if (!pContentControl->GetComboBox() && !pContentControl->GetDropDown()) + { + return; + } + + it = rArguments.find("selected"); + if (it == rArguments.end()) + { + return; + } + + sal_Int32 nSelection = it->second.toInt32(); + pContentControl->SetSelectedListItem(nSelection); + pWrtShell->GotoContentControl(rFormatContentControl); + } + else if (it->second == "picture") + { + it = rArguments.find("changed"); + if (it == rArguments.end()) + { + return; + } + + SwView* pView = m_pDocShell->GetView(); + if (!pView) + { + return; + } + + // The current placeholder is selected, so this will replace, not insert. + SfxStringItem aItem(SID_INSERT_GRAPHIC, it->second); + pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_CHANGE_PICTURE, + SfxCallMode::SYNCHRON, { &aItem }); + } + else if (it->second == "date") + { + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + const SwPosition* pStart = pWrtShell->GetCursor()->Start(); + SwTextNode* pTextNode = pStart->GetNode().GetTextNode(); + if (!pTextNode) + { + return; + } + + SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->GetContentIndex(), + RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); + if (!pAttr) + { + return; + } + + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + const SwFormatContentControl& rFormatContentControl + = pTextContentControl->GetContentControl(); + std::shared_ptr<SwContentControl> pContentControl + = rFormatContentControl.GetContentControl(); + if (!pContentControl->GetDate()) + { + return; + } + + it = rArguments.find("selected"); + if (it == rArguments.end()) + { + return; + } + + OUString aSelectedDate = it->second.replaceAll("T00:00:00Z", ""); + SwDoc& rDoc = pTextNode->GetDoc(); + SvNumberFormatter* pNumberFormatter = rDoc.GetNumberFormatter(); + sal_uInt32 nFormat + = pNumberFormatter->GetEntryKey(SELECTED_DATE_FORMAT, LANGUAGE_ENGLISH_US); + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + sal_Int32 nCheckPos = 0; + SvNumFormatType nType; + OUString sFormat = SELECTED_DATE_FORMAT; + pNumberFormatter->PutEntry(sFormat, nCheckPos, nType, nFormat, LANGUAGE_ENGLISH_US); + } + + if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + return; + } + + double dCurrentDate = 0; + pNumberFormatter->IsNumberFormat(aSelectedDate, nFormat, dCurrentDate); + pContentControl->SetSelectedDate(dCurrentDate); + pWrtShell->GotoContentControl(rFormatContentControl); + } +} + +int SwXTextDocument::getPart() +{ + SolarMutexGuard aGuard; + + SwView* pView = m_pDocShell->GetView(); + if (!pView) + return 0; + + return pView->getPart(); +} + +OUString SwXTextDocument::getPartName(int nPart) +{ + return SwResId(STR_PAGE) + OUString::number(nPart + 1); +} + +OUString SwXTextDocument::getPartHash(int nPart) +{ + OUString sPart(SwResId(STR_PAGE) + OUString::number(nPart + 1)); + + return OUString::number(sPart.hashCode()); +} + +VclPtr<vcl::Window> SwXTextDocument::getDocWindow() +{ + SolarMutexGuard aGuard; + SwView* pView = m_pDocShell->GetView(); + if (!pView) + return {}; + + if (VclPtr<vcl::Window> pWindow = SfxLokHelper::getInPlaceDocWindow(pView)) + return pWindow; + + return &(pView->GetEditWin()); +} + +void SwXTextDocument::initializeForTiledRendering(const css::uno::Sequence<css::beans::PropertyValue>& rArguments) +{ + SolarMutexGuard aGuard; + + SwViewShell* pViewShell = m_pDocShell->GetWrtShell(); + + SwView* pView = m_pDocShell->GetView(); + if (!pView) + return; + + pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true); + + // Tiled rendering defaults. + SwViewOption aViewOption(*pViewShell->GetViewOptions()); + aViewOption.SetHardBlank(false); + + // Disable field shadings: the result would depend on the cursor position. + aViewOption.SetAppearanceFlag(ViewOptFlags::FieldShadings, false); + // The fancy header/footer controls don't work in tiled mode anyway, so + // explicitly disable them to enable skipping invalidating the view for + // the case of clicking in the header area of a document with no headers + aViewOption.SetUseHeaderFooterMenu(false); + + OUString sOrigAuthor = SW_MOD()->GetRedlineAuthor(SW_MOD()->GetRedlineAuthor()); + OUString sAuthor; + + for (const beans::PropertyValue& rValue : rArguments) + { + if (rValue.Name == ".uno:HideWhitespace" && rValue.Value.has<bool>()) + aViewOption.SetHideWhitespaceMode(rValue.Value.get<bool>()); + else if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has<bool>()) + aViewOption.SetAppearanceFlag(ViewOptFlags::Shadow , rValue.Value.get<bool>()); + else if (rValue.Name == ".uno:Author" && rValue.Value.has<OUString>()) + { + sAuthor = rValue.Value.get<OUString>(); + // Store the author name in the view. + pView->SetRedlineAuthor(sAuthor); + // Let the actual author name pick up the value from the current + // view, which would normally happen only during the next view + // switch. + m_pDocShell->SetView(pView); + } + else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has<bool>()) + aViewOption.SetOnlineSpell(rValue.Value.get<bool>()); + } + + if (!sAuthor.isEmpty() && sAuthor != sOrigAuthor) + { + SwView* pFirstView = static_cast<SwView*>(SfxViewShell::GetFirst()); + if (pFirstView && SfxViewShell::GetNext(*pFirstView) == nullptr) + { + if (SwEditShell* pShell = &pFirstView->GetWrtShell()) + { + pShell->SwViewShell::UpdateFields(true); + pShell->ResetModified(); + } + } + } + + // Set the initial zoom value to 1; usually it is set in setClientZoom and + // SwViewShell::PaintTile; zoom value is used for chart in place + // editing, see postMouseEvent and setGraphicSelection methods. + aViewOption.SetZoom(1 * 100); + + aViewOption.SetPostIts(comphelper::LibreOfficeKit::isTiledAnnotations()); + pViewShell->ApplyViewOptions(aViewOption); + + // position the pages again after setting view options. Eg: if postit + // rendering is false, then there would be no sidebar, so width of the + // document needs to be adjusted + pViewShell->GetLayout()->CheckViewLayout( pViewShell->GetViewOptions(), nullptr ); + + // Disable map mode, so that it's possible to send mouse event coordinates + // directly in twips. + SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin(); + rEditWin.EnableMapMode(false); + + // when the "This document may contain formatting or content that cannot + // be saved..." dialog appears, it is auto-cancelled with tiled rendering, + // causing 'Save' being disabled; so let's always save to the original + // format + auto xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges); + xChanges->commit(); + + // disable word auto-completion suggestions, the tooltips are not visible, + // and the editeng-like auto-completion is annoying + SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags().bAutoCompleteWords = false; + + // don't change the whitespace at the beginning of paragraphs, this is + // annoying when taking minutes without further formatting + SwEditShell::GetAutoFormatFlags()->bAFormatByInpDelSpacesAtSttEnd = false; +} + +void SwXTextDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode) +{ + SolarMutexGuard aGuard; + SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode); +} + +void SwXTextDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier) +{ + SolarMutexGuard aGuard; + + SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell(); + if (!pWrtViewShell) + { + return; + } + + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip); + + if (SfxLokHelper::testInPlaceComponentMouseEventHit( + m_pDocShell->GetView(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale)) + return; + + // try to forward mouse event to controls + SwDrawModel* pDrawLayer = GetDocOrThrow().getIDocumentDrawModelAccess().GetDrawModel(); + SdrPage* pPage = pDrawLayer->GetPage(sal_uInt16(0)); + SdrView* pDrawView = pWrtViewShell->GetDrawView(); + SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin(); + Point aPointTwip(nX, nY); + Point aPointHMMDraw = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100); + if (LokControlHandler::postMouseEvent(pPage, pDrawView, rEditWin, nType, aPointHMMDraw, nCount, nButtons, nModifier)) + return; + + LokMouseEventData aMouseEventData(nType, Point(nX, nY), nCount, + MouseEventModifiers::SIMPLECLICK, + nButtons, nModifier); + SfxLokHelper::postMouseEventAsync(&rEditWin, aMouseEventData); +} + +void SwXTextDocument::setTextSelection(int nType, int nX, int nY) +{ + SolarMutexGuard aGuard; + + SfxViewShell* pViewShell = m_pDocShell->GetView(); + LokChartHelper aChartHelper(pViewShell); + if (aChartHelper.setTextSelection(nType, nX, nY)) + return; + + SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin(); + switch (nType) + { + case LOK_SETTEXTSELECTION_START: + rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/false, /*bClearMark=*/false); + break; + case LOK_SETTEXTSELECTION_END: + rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/false); + break; + case LOK_SETTEXTSELECTION_RESET: + rEditWin.SetCursorTwipPosition(Point(nX, nY), /*bPoint=*/true, /*bClearMark=*/true); + break; + default: + assert(false); + break; + } +} + +uno::Reference<datatransfer::XTransferable> SwXTextDocument::getSelection() +{ + SolarMutexGuard aGuard; + + uno::Reference<datatransfer::XTransferable> xTransferable; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + if (SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr) + { + if (pSdrView->GetTextEditObject()) + { + // Editing shape text + EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView(); + xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection()); + } + } + + if (SwPostItMgr* pPostItMgr = m_pDocShell->GetView()->GetPostItMgr()) + { + if (sw::annotation::SwAnnotationWin* pWin = pPostItMgr->GetActiveSidebarWin()) + { + // Editing postit text. + EditView& rEditView = pWin->GetOutlinerView()->GetEditView(); + xTransferable = rEditView.GetEditEngine()->CreateTransferable(rEditView.GetSelection()); + } + } + + if (!xTransferable.is() && pWrtShell) + xTransferable = new SwTransferable(*pWrtShell); + + return xTransferable; +} + +void SwXTextDocument::setGraphicSelection(int nType, int nX, int nY) +{ + SolarMutexGuard aGuard; + + SwViewShell* pWrtViewShell = m_pDocShell->GetWrtShell(); + SwViewOption aOption(*(pWrtViewShell->GetViewOptions())); + double fScale = aOption.GetZoom() / o3tl::convert(100.0, o3tl::Length::px, o3tl::Length::twip); + + SfxViewShell* pViewShell = m_pDocShell->GetView(); + LokChartHelper aChartHelper(pViewShell); + if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale)) + return; + + SwEditWin& rEditWin = m_pDocShell->GetView()->GetEditWin(); + switch (nType) + { + case LOK_SETGRAPHICSELECTION_START: + rEditWin.SetGraphicTwipPosition(/*bStart=*/true, Point(nX, nY)); + break; + case LOK_SETGRAPHICSELECTION_END: + rEditWin.SetGraphicTwipPosition(/*bStart=*/false, Point(nX, nY)); + break; + default: + assert(false); + break; + } +} + +void SwXTextDocument::resetSelection() +{ + SolarMutexGuard aGuard; + + SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell(); + pWrtShell->ResetSelect(nullptr, false); +} + +void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) +{ + SystemGraphicsData aData; + aData.nSize = sizeof(SystemGraphicsData); + #if defined(_WIN32) + sal_Int64 nWindowHandle; + Parent >>= nWindowHandle; + aData.hWnd = reinterpret_cast<HWND>(nWindowHandle); + ScopedVclPtrInstance<VirtualDevice> xDevice(aData, Size(1, 1), DeviceFormat::WITHOUT_ALPHA); + paintTile(*xDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight); + #else + // TODO: support other platforms + (void)Parent; + (void)nOutputWidth; + (void)nOutputHeight; + (void)nTilePosX; + (void)nTilePosY; + (void)nTileWidth; + (void)nTileHeight; + #endif +} + +/** + * retrieve languages already used in current document + */ +uno::Sequence< lang::Locale > SAL_CALL SwXTextDocument::getDocumentLanguages( + ::sal_Int16 nScriptTypes, + ::sal_Int16 nMaxCount ) +{ + SolarMutexGuard aGuard; + + // possible canonical values for nScriptTypes + // any bit wise combination is allowed + const sal_Int16 nLatin = 0x001; + const sal_Int16 nAsian = 0x002; + const sal_Int16 nComplex = 0x004; + + // script types for which to get the languages + const bool bLatin = 0 != (nScriptTypes & nLatin); + const bool bAsian = 0 != (nScriptTypes & nAsian); + const bool bComplex = 0 != (nScriptTypes & nComplex); + + if (nScriptTypes < nLatin || nScriptTypes > (nLatin | nAsian | nComplex)) + throw IllegalArgumentException("nScriptTypes ranges from 1 to 7!", Reference< XInterface >(), 1); + if (!m_pDocShell) + throw DisposedException(); + SwDoc& rDoc = GetDocOrThrow(); + + // avoid duplicate values + std::set< LanguageType > aAllLangs; + + //USER STYLES + + const SwCharFormats *pFormats = rDoc.GetCharFormats(); + for(size_t i = 0; i < pFormats->size(); ++i) + { + const SwAttrSet &rAttrSet = (*pFormats)[i]->GetAttrSet(); + LanguageType nLang = LANGUAGE_DONTKNOW; + if (bLatin) + { + nLang = rAttrSet.GetLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + } + + const SwTextFormatColls *pColls = rDoc.GetTextFormatColls(); + for (size_t i = 0; i < pColls->size(); ++i) + { + const SwAttrSet &rAttrSet = (*pColls)[i]->GetAttrSet(); + LanguageType nLang = LANGUAGE_DONTKNOW; + if (bLatin) + { + nLang = rAttrSet.GetLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + nLang = rAttrSet.GetCJKLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + nLang = rAttrSet.GetCTLLanguage( false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + } + + //AUTO STYLES + const IStyleAccess::SwAutoStyleFamily aFam[2] = + { + IStyleAccess::AUTO_STYLE_CHAR, + IStyleAccess::AUTO_STYLE_PARA + }; + for (IStyleAccess::SwAutoStyleFamily i : aFam) + { + std::vector< std::shared_ptr<SfxItemSet> > rStyles; + rDoc.GetIStyleAccess().getAllStyles(rStyles, i); + while (!rStyles.empty()) + { + std::shared_ptr<SfxItemSet> pStyle = rStyles.back(); + rStyles.pop_back(); + const SfxItemSet *pSet = pStyle.get(); + + LanguageType nLang = LANGUAGE_DONTKNOW; + if (bLatin) + { + assert(pSet); + nLang = pSet->Get( RES_CHRATR_LANGUAGE, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + assert(pSet); + nLang = pSet->Get( RES_CHRATR_CJK_LANGUAGE, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + assert(pSet); + nLang = pSet->Get( RES_CHRATR_CTL_LANGUAGE, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + } + } + + //TODO/mba: it's a strange concept that a view is needed to retrieve core data + SwWrtShell *pWrtSh = m_pDocShell->GetWrtShell(); + SdrView *pSdrView = pWrtSh->GetDrawView(); + + if( pSdrView ) + { + SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner(); + if(pOutliner) + { + EditEngine& rEditEng = const_cast<EditEngine&>(pOutliner->GetEditEngine()); + sal_Int32 nParCount = pOutliner->GetParagraphCount(); + for (sal_Int32 nPar=0; nPar<nParCount; nPar++) + { + //every paragraph + std::vector<sal_Int32> aPortions; + rEditEng.GetPortions( nPar, aPortions ); + + for ( size_t nPos = aPortions.size(); nPos; ) + { + //every position + --nPos; + sal_Int32 nEnd = aPortions[ nPos ]; + sal_Int32 nStart = nPos ? aPortions[ nPos - 1 ] : 0; + ESelection aSelection( nPar, nStart, nPar, nEnd ); + SfxItemSet aAttr = rEditEng.GetAttribs( aSelection ); + + LanguageType nLang = LANGUAGE_DONTKNOW; + if (bLatin) + { + nLang = aAttr.Get( EE_CHAR_LANGUAGE, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bAsian) + { + nLang = aAttr.Get( EE_CHAR_LANGUAGE_CJK, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + if (bComplex) + { + nLang = aAttr.Get( EE_CHAR_LANGUAGE_CTL, false ).GetLanguage(); + if (nLang != LANGUAGE_DONTKNOW && nLang != LANGUAGE_SYSTEM) + aAllLangs.insert( nLang ); + } + } + } + } + } + // less than nMaxCount languages + if (nMaxCount > static_cast< sal_Int16 >( aAllLangs.size() )) + nMaxCount = static_cast< sal_Int16 >( aAllLangs.size() ); + + // build return value + uno::Sequence< lang::Locale > aLanguages( nMaxCount ); + lang::Locale* pLanguage = aLanguages.getArray(); + if (nMaxCount > 0) + { + sal_Int32 nCount = 0; + for (const auto& rLang : aAllLangs) + { + if (nCount >= nMaxCount) + break; + if (LANGUAGE_NONE != rLang) + { + pLanguage[nCount] = LanguageTag::convertToLocale( rLang ); + pLanguage[nCount].Language = SvtLanguageTable::GetLanguageString( rLang ); + nCount += 1; + } + } + } + + return aLanguages; +} + +SwXLinkTargetSupplier::SwXLinkTargetSupplier(SwXTextDocument& rxDoc) : + m_pxDoc(&rxDoc) +{ + m_sTables = SwResId(STR_CONTENT_TYPE_TABLE); + m_sFrames = SwResId(STR_CONTENT_TYPE_FRAME); + m_sGraphics = SwResId(STR_CONTENT_TYPE_GRAPHIC); + m_sOLEs = SwResId(STR_CONTENT_TYPE_OLE); + m_sSections = SwResId(STR_CONTENT_TYPE_REGION); + m_sOutlines = SwResId(STR_CONTENT_TYPE_OUTLINE); + m_sBookmarks = SwResId(STR_CONTENT_TYPE_BOOKMARK); + m_sDrawingObjects = SwResId(STR_CONTENT_TYPE_DRAWOBJECT); +} + +SwXLinkTargetSupplier::~SwXLinkTargetSupplier() +{ +} + +Any SwXLinkTargetSupplier::getByName(const OUString& rName) +{ + Any aRet; + if(!m_pxDoc) + throw RuntimeException("No document available"); + OUString sSuffix("|"); + if(rName == m_sTables) + { + sSuffix += "table"; + + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + m_pxDoc->getTextTables(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sFrames) + { + sSuffix += "frame"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + m_pxDoc->getTextFrames(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sSections) + { + sSuffix += "region"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + m_pxDoc->getTextSections(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sGraphics) + { + sSuffix += "graphic"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + m_pxDoc->getGraphicObjects(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sOLEs) + { + sSuffix += "ole"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + m_pxDoc->getEmbeddedObjects(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sOutlines) + { + sSuffix += "outline"; + Reference< XNameAccess > xTables = new SwXLinkNameAccessWrapper( + *m_pxDoc, rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xTables, UNO_QUERY); + } + else if(rName == m_sBookmarks) + { + sSuffix.clear(); + Reference< XNameAccess > xBkms = new SwXLinkNameAccessWrapper( + m_pxDoc->getBookmarks(), rName, sSuffix ); + aRet <<= Reference< XPropertySet >(xBkms, UNO_QUERY); + } + else if(rName == m_sDrawingObjects) + { + sSuffix += "drawingobject"; + Reference<XNameAccess> xDrawingObjects = new SwXLinkNameAccessWrapper( + *m_pxDoc, rName, sSuffix); + aRet <<= Reference<XPropertySet>(xDrawingObjects, UNO_QUERY); + } + else + throw NoSuchElementException(); + return aRet; +} + +Sequence< OUString > SwXLinkTargetSupplier::getElementNames() +{ + return { m_sTables, + m_sFrames, + m_sGraphics, + m_sOLEs, + m_sSections, + m_sOutlines, + m_sBookmarks, + m_sDrawingObjects }; +} + +sal_Bool SwXLinkTargetSupplier::hasByName(const OUString& rName) +{ + if( rName == m_sTables || + rName == m_sFrames || + rName == m_sGraphics|| + rName == m_sOLEs || + rName == m_sSections || + rName == m_sOutlines || + rName == m_sBookmarks || + rName == m_sDrawingObjects ) + return true; + return false; +} + +uno::Type SwXLinkTargetSupplier::getElementType() +{ + return cppu::UnoType<XPropertySet>::get(); + +} + +sal_Bool SwXLinkTargetSupplier::hasElements() +{ + return nullptr != m_pxDoc; +} + +OUString SwXLinkTargetSupplier::getImplementationName() +{ + return "SwXLinkTargetSupplier"; +} + +sal_Bool SwXLinkTargetSupplier::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXLinkTargetSupplier::getSupportedServiceNames() +{ + Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" }; + return aRet; +} + +SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper( + Reference< XNameAccess > const & xAccess, OUString aLinkDisplayName, OUString sSuffix ) : + m_xRealAccess(xAccess), + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + m_sLinkSuffix(std::move(sSuffix)), + m_sLinkDisplayName(std::move(aLinkDisplayName)), + m_pxDoc(nullptr) +{ +} + +SwXLinkNameAccessWrapper::SwXLinkNameAccessWrapper(SwXTextDocument& rxDoc, + OUString aLinkDisplayName, OUString sSuffix) : + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + m_sLinkSuffix(std::move(sSuffix)), + m_sLinkDisplayName(std::move(aLinkDisplayName)), + m_pxDoc(&rxDoc) +{ +} + +SwXLinkNameAccessWrapper::~SwXLinkNameAccessWrapper() +{ +} + +Any SwXLinkNameAccessWrapper::getByName(const OUString& rName) +{ + Any aRet; + bool bFound = false; + //cut link extension and call the real NameAccess + OUString sParam = rName; + OUString sSuffix(m_sLinkSuffix); + if(sParam.getLength() > sSuffix.getLength() ) + { + std::u16string_view sCmp = sParam.subView(sParam.getLength() - sSuffix.getLength(), + sSuffix.getLength()); + if(sCmp == sSuffix) + { + if(m_pxDoc) + { + sParam = sParam.copy(0, sParam.getLength() - sSuffix.getLength()); + if(!m_pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc(); + + if (sSuffix == "|outline") + { + const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); + + for (size_t i = 0; i < nOutlineCount && !bFound; ++i) + { + if(sParam == lcl_CreateOutlineString(i, pDoc)) + { + OUString sOutlineText = + pDoc->getIDocumentOutlineNodes().getOutlineText( + i, pDoc->GetDocShell()->GetWrtShell()->GetLayout()); + sal_Int32 nOutlineLevel = pDoc->getIDocumentOutlineNodes().getOutlineLevel(i); + Reference<XPropertySet> xOutline = + new SwXOutlineTarget(sParam, sOutlineText, nOutlineLevel); + aRet <<= xOutline; + bFound = true; + } + } + } + else if (sSuffix == "|drawingobject") + { + SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + if (pModel) + { + SdrPage* pPage = pModel->GetPage(0); + for (const rtl::Reference<SdrObject>& pObj : *pPage) + { + if (sParam == pObj->GetName()) + { + Reference<XPropertySet> xDrawingObject = new SwXDrawingObjectTarget(sParam); + aRet <<= xDrawingObject; + bFound = true; + break; + } + } + } + } + } + else + { + aRet = m_xRealAccess->getByName(sParam.copy(0, sParam.getLength() - sSuffix.getLength())); + Reference< XInterface > xInt; + if(!(aRet >>= xInt)) + throw RuntimeException("Could not retrieve property"); + Reference< XPropertySet > xProp(xInt, UNO_QUERY); + aRet <<= xProp; + bFound = true; + } + } + } + if(!bFound) + throw NoSuchElementException(); + return aRet; +} + +Sequence< OUString > SwXLinkNameAccessWrapper::getElementNames() +{ + Sequence< OUString > aRet; + if(m_pxDoc) + { + if(!m_pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc(); + if (m_sLinkSuffix == "|outline") + { + const SwOutlineNodes& rOutlineNodes = pDoc->GetNodes().GetOutLineNds(); + const size_t nOutlineCount = rOutlineNodes.size(); + aRet.realloc(nOutlineCount); + OUString* pResArr = aRet.getArray(); + for (size_t i = 0; i < nOutlineCount; ++i) + { + OUString sEntry = lcl_CreateOutlineString(i, pDoc) + "|outline"; + pResArr[i] = sEntry; + } + } + else if (m_sLinkSuffix == "|drawingobject") + { + SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + if(pModel) + { + SdrPage* pPage = pModel->GetPage(0); + const size_t nObjCount = pPage->GetObjCount(); + aRet.realloc(nObjCount); + OUString* pResArr = aRet.getArray(); + auto j = 0; + for (const rtl::Reference<SdrObject>& pObj : *pPage) + { + if (!pObj->GetName().isEmpty()) + pResArr[j++] = pObj->GetName() + "|drawingobject"; + } + } + } + } + else + { + const Sequence< OUString > aOrg = m_xRealAccess->getElementNames(); + aRet.realloc(aOrg.getLength()); + std::transform(aOrg.begin(), aOrg.end(), aRet.getArray(), + [this](const OUString& rOrg) -> OUString { return rOrg + m_sLinkSuffix; }); + } + return aRet; +} + +sal_Bool SwXLinkNameAccessWrapper::hasByName(const OUString& rName) +{ + bool bRet = false; + OUString sParam(rName); + if(sParam.getLength() > m_sLinkSuffix.getLength() ) + { + std::u16string_view sCmp = sParam.subView(sParam.getLength() - m_sLinkSuffix.getLength(), + m_sLinkSuffix.getLength()); + if(sCmp == m_sLinkSuffix) + { + sParam = sParam.copy(0, sParam.getLength() - m_sLinkSuffix.getLength()); + if(m_pxDoc) + { + if(!m_pxDoc->GetDocShell()) + throw RuntimeException("No document shell available"); + SwDoc* pDoc = m_pxDoc->GetDocShell()->GetDoc(); + if (m_sLinkSuffix == "|outline") + { + const size_t nOutlineCount = pDoc->GetNodes().GetOutLineNds().size(); + + for (size_t i = 0; i < nOutlineCount && !bRet; ++i) + { + if(sParam == lcl_CreateOutlineString(i, pDoc)) + { + bRet = true; + } + } + } + else if (m_sLinkSuffix == "|drawingobject") + { + SwDrawModel* pModel = pDoc->getIDocumentDrawModelAccess().GetDrawModel(); + if (pModel) + { + SdrPage* pPage = pModel->GetPage(0); + for (const rtl::Reference<SdrObject>& pObj : *pPage) + { + if (sParam == pObj->GetName()) + { + bRet = true; + break; + } + } + } + } + } + else + { + bRet = m_xRealAccess->hasByName(sParam); + } + } + } + return bRet; +} + +uno::Type SwXLinkNameAccessWrapper::getElementType() +{ + return cppu::UnoType<XPropertySet>::get(); +} + +sal_Bool SwXLinkNameAccessWrapper::hasElements() +{ + bool bRet = false; + if(m_pxDoc) + { + OSL_FAIL("not implemented"); + } + else + { + bRet = m_xRealAccess->hasElements(); + } + return bRet; +} + +Reference< XPropertySetInfo > SwXLinkNameAccessWrapper::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXLinkNameAccessWrapper::setPropertyValue( + const OUString& rPropName, const Any& ) +{ + throw UnknownPropertyException(rPropName); +} + +static Any lcl_GetDisplayBitmap(std::u16string_view sLinkSuffix) +{ + Any aRet; + if(!sLinkSuffix.empty()) + sLinkSuffix = sLinkSuffix.substr(1); + OUString sImgId; + + if(sLinkSuffix == u"outline") + sImgId = RID_BMP_NAVI_OUTLINE; + else if(sLinkSuffix == u"table") + sImgId = RID_BMP_NAVI_TABLE; + else if(sLinkSuffix == u"frame") + sImgId = RID_BMP_NAVI_FRAME; + else if(sLinkSuffix == u"graphic") + sImgId = RID_BMP_NAVI_GRAPHIC; + else if(sLinkSuffix == u"ole") + sImgId = RID_BMP_NAVI_OLE; + else if(sLinkSuffix.empty()) + sImgId = RID_BMP_NAVI_BOOKMARK; + else if(sLinkSuffix == u"region") + sImgId = RID_BMP_NAVI_REGION; + else if(sLinkSuffix == u"drawingobject") + sImgId = RID_BMP_NAVI_DRAWOBJECT; + + if (!sImgId.isEmpty()) + { + aRet <<= VCLUnoHelper::CreateBitmap(BitmapEx(sImgId)); + } + return aRet; +} + +Any SwXLinkNameAccessWrapper::getPropertyValue(const OUString& rPropertyName) +{ + Any aRet; + if( rPropertyName == UNO_LINK_DISPLAY_NAME ) + { + aRet <<= m_sLinkDisplayName; + } + else if( rPropertyName == UNO_LINK_DISPLAY_BITMAP ) + { + aRet = lcl_GetDisplayBitmap(m_sLinkSuffix); + } + else + throw UnknownPropertyException(rPropertyName); + return aRet; +} + +void SwXLinkNameAccessWrapper::addPropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{} + +void SwXLinkNameAccessWrapper::removePropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{} + +void SwXLinkNameAccessWrapper::addVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{} + +void SwXLinkNameAccessWrapper::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{} + +Reference< XNameAccess > SwXLinkNameAccessWrapper::getLinks() +{ + return this; +} + +OUString SwXLinkNameAccessWrapper::getImplementationName() +{ + return "SwXLinkNameAccessWrapper"; +} + +sal_Bool SwXLinkNameAccessWrapper::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXLinkNameAccessWrapper::getSupportedServiceNames() +{ + Sequence< OUString > aRet { "com.sun.star.document.LinkTargets" }; + return aRet; +} + +SwXOutlineTarget::SwXOutlineTarget(OUString aOutlineText, OUString aActualText, + const sal_Int32 nOutlineLevel) : + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + m_sOutlineText(std::move(aOutlineText)), + m_sActualText(std::move(aActualText)), + m_nOutlineLevel(nOutlineLevel) +{ +} + +SwXOutlineTarget::~SwXOutlineTarget() +{ +} + +Reference< XPropertySetInfo > SwXOutlineTarget::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXOutlineTarget::setPropertyValue( + const OUString& rPropertyName, const Any& /*aValue*/) +{ + throw UnknownPropertyException(rPropertyName); +} + +Any SwXOutlineTarget::getPropertyValue(const OUString& rPropertyName) +{ + if (rPropertyName != UNO_LINK_DISPLAY_NAME && rPropertyName != "ActualOutlineName" && + rPropertyName != "OutlineLevel") + throw UnknownPropertyException(rPropertyName); + + if (rPropertyName == "ActualOutlineName") + return Any(m_sActualText); + + if (rPropertyName == "OutlineLevel") + return Any(m_nOutlineLevel); + + return Any(m_sOutlineText); +} + +void SwXOutlineTarget::addPropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXOutlineTarget::removePropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXOutlineTarget::addVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ +} + +void SwXOutlineTarget::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ +} + +OUString SwXOutlineTarget::getImplementationName() +{ + return "SwXOutlineTarget"; +} + +sal_Bool SwXOutlineTarget::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString > SwXOutlineTarget::getSupportedServiceNames() +{ + Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" }; + + return aRet; +} + +SwXDrawingObjectTarget::SwXDrawingObjectTarget(OUString aDrawingObjectText) : + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_LINK_TARGET)), + m_sDrawingObjectText(std::move(aDrawingObjectText)) +{ +} + +SwXDrawingObjectTarget::~SwXDrawingObjectTarget() +{ +} + +Reference< XPropertySetInfo > SwXDrawingObjectTarget::getPropertySetInfo() +{ + static Reference< XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo(); + return xRet; +} + +void SwXDrawingObjectTarget::setPropertyValue( + const OUString& rPropertyName, const Any& /*aValue*/) +{ + throw UnknownPropertyException(rPropertyName); +} + +Any SwXDrawingObjectTarget::getPropertyValue(const OUString& rPropertyName) +{ + if(rPropertyName != UNO_LINK_DISPLAY_NAME) + throw UnknownPropertyException(rPropertyName); + + return Any(m_sDrawingObjectText); +} + +void SwXDrawingObjectTarget::addPropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXDrawingObjectTarget::removePropertyChangeListener( + const OUString& /*PropertyName*/, const Reference< XPropertyChangeListener > & /*aListener*/) +{ +} + +void SwXDrawingObjectTarget::addVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ +} + +void SwXDrawingObjectTarget::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener > & /*aListener*/) +{ +} + +OUString SwXDrawingObjectTarget::getImplementationName() +{ + return "SwXDrawingObjectTarget"; +} + +sal_Bool SwXDrawingObjectTarget::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +Sequence< OUString > SwXDrawingObjectTarget::getSupportedServiceNames() +{ + Sequence<OUString> aRet { "com.sun.star.document.LinkTarget" }; + + return aRet; +} + +SwXDocumentPropertyHelper::SwXDocumentPropertyHelper(SwDoc& rDoc) : +SvxUnoForbiddenCharsTable ( rDoc.getIDocumentSettingAccess().getForbiddenCharacterTable() ) +,m_pDoc(&rDoc) +{ +} + +SwXDocumentPropertyHelper::~SwXDocumentPropertyHelper() +{ +} + +Reference<XInterface> SwXDocumentPropertyHelper::GetDrawTable(SwCreateDrawTable nWhich) +{ + Reference<XInterface> xRet; + if(m_pDoc) + { + switch(nWhich) + { + // #i52858# + // assure that Draw model is created, if it doesn't exist. + case SwCreateDrawTable::Dash : + if(!m_xDashTable.is()) + m_xDashTable = SvxUnoDashTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xDashTable; + break; + case SwCreateDrawTable::Gradient : + if(!m_xGradientTable.is()) + m_xGradientTable = SvxUnoGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xGradientTable; + break; + case SwCreateDrawTable::Hatch : + if(!m_xHatchTable.is()) + m_xHatchTable = SvxUnoHatchTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xHatchTable; + break; + case SwCreateDrawTable::Bitmap : + if(!m_xBitmapTable.is()) + m_xBitmapTable = SvxUnoBitmapTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xBitmapTable; + break; + case SwCreateDrawTable::TransGradient: + if(!m_xTransGradientTable.is()) + m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xTransGradientTable; + break; + case SwCreateDrawTable::Marker : + if(!m_xMarkerTable.is()) + m_xMarkerTable = SvxUnoMarkerTable_createInstance( m_pDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel() ); + xRet = m_xMarkerTable; + break; + case SwCreateDrawTable::Defaults: + if(!m_xDrawDefaults.is()) + m_xDrawDefaults = cppu::getXWeak(new SwSvxUnoDrawPool(*m_pDoc)); + xRet = m_xDrawDefaults; + break; +#if OSL_DEBUG_LEVEL > 0 + default: OSL_FAIL("which table?"); +#endif + } + } + return xRet; +} + +void SwXDocumentPropertyHelper::Invalidate() +{ + m_xDashTable = nullptr; + m_xGradientTable = nullptr; + m_xHatchTable = nullptr; + m_xBitmapTable = nullptr; + m_xTransGradientTable = nullptr; + m_xMarkerTable = nullptr; + m_xDrawDefaults = nullptr; + m_pDoc = nullptr; + SvxUnoForbiddenCharsTable::mxForbiddenChars.reset(); +} + +void SwXDocumentPropertyHelper::onChange() +{ + if(m_pDoc) + m_pDoc->getIDocumentState().SetModified(); +} + +SwViewOptionAdjust_Impl::SwViewOptionAdjust_Impl( + SwViewShell& rSh, const SwViewOption &rViewOptions) + : m_pShell(&rSh) + , m_aOldViewOptions( rViewOptions ) +{ +} + +SwViewOptionAdjust_Impl::~SwViewOptionAdjust_Impl() +{ + if (m_pShell) + { + m_pShell->ApplyViewOptions( m_aOldViewOptions ); + } +} + +void +SwViewOptionAdjust_Impl::AdjustViewOptions(SwPrintData const*const pPrtOptions, bool setShowPlaceHoldersInPDF) +{ + // to avoid unnecessary reformatting the view options related to the content + // below should only change if necessary, that is if respective content is present + const bool bContainsHiddenChars = m_pShell->GetDoc()->ContainsHiddenChars(); + const SwFieldType* pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText ); + const bool bContainsHiddenFields = pFieldType && pFieldType->HasWriterListeners(); + pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenPara ); + const bool bContainsHiddenParagraphs = pFieldType && pFieldType->HasWriterListeners(); + pFieldType = m_pShell->GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::JumpEdit ); + const bool bContainsPlaceHolders = pFieldType && pFieldType->HasWriterListeners(); + const bool bContainsFields = m_pShell->IsAnyFieldInDoc(); + + SwViewOption aRenderViewOptions( m_aOldViewOptions ); + + // disable anything in the view that should not be printed (or exported to PDF) by default + // (see also dialog "Tools/Options - StarOffice Writer - Formatting Aids" + // in section "Display of ...") + aRenderViewOptions.SetParagraph( false ); // paragraph end + aRenderViewOptions.SetSoftHyph( false ); // aka custom hyphens + aRenderViewOptions.SetBlank( false ); // spaces + aRenderViewOptions.SetHardBlank( false ); // non-breaking spaces + aRenderViewOptions.SetTab( false ); // tabs + aRenderViewOptions.SetShowBookmarks( false ); // bookmarks + aRenderViewOptions.SetLineBreak( false ); // breaks (type 1) + aRenderViewOptions.SetPageBreak( false ); // breaks (type 2) + aRenderViewOptions.SetColumnBreak( false ); // breaks (type 3) + bool bVal = pPrtOptions && pPrtOptions->m_bPrintHiddenText; + if (bContainsHiddenChars) + aRenderViewOptions.SetShowHiddenChar( bVal ); // hidden text + if (bContainsHiddenFields) + aRenderViewOptions.SetShowHiddenField( bVal ); + if (bContainsHiddenParagraphs) + aRenderViewOptions.SetShowHiddenPara( bVal ); + + if (bContainsPlaceHolders) + { + // should always be printed in PDF export! + bVal = !pPrtOptions ? setShowPlaceHoldersInPDF : pPrtOptions->m_bPrintTextPlaceholder; + aRenderViewOptions.SetShowPlaceHolderFields( bVal ); + } + + if (bContainsFields) + aRenderViewOptions.SetFieldName( false ); + + // we need to set this flag in order to get to see the visible effect of + // some of the above settings (needed for correct rendering) + aRenderViewOptions.SetViewMetaChars( true ); + + if (m_aOldViewOptions != aRenderViewOptions) // check if reformatting is necessary + { + aRenderViewOptions.SetPrinting( pPrtOptions != nullptr ); + m_pShell->ApplyViewOptions( aRenderViewOptions ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx new file mode 100644 index 0000000000..43f2c7a62c --- /dev/null +++ b/sw/source/uibase/uno/unotxvw.cxx @@ -0,0 +1,1707 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <viscrs.hxx> +#include <o3tl/any.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/viewfrm.hxx> +#include <cmdid.h> +#include <docsh.hxx> +#include <rubylist.hxx> +#include <doc.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <unotxvw.hxx> +#include <unodispatch.hxx> +#include <unomap.hxx> +#include <unoprnms.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <unomod.hxx> +#include <unoframe.hxx> +#include <unocrsr.hxx> +#include <wrtsh.hxx> +#include <unotbl.hxx> +#include <svx/fmshell.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdouno.hxx> +#include <editeng/pbinitem.hxx> +#include <pagedesc.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <frmatr.hxx> +#include <IMark.hxx> +#include <unodraw.hxx> +#include <svx/svdpagv.hxx> +#include <ndtxt.hxx> +#include <SwStyleNameMapper.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/drawing/ShapeCollection.hpp> +#include <editeng/outliner.hxx> +#include <editeng/editview.hxx> +#include <unoparagraph.hxx> +#include <unocrsrhelper.hxx> +#include <unotextrange.hxx> +#include <sfx2/docfile.hxx> +#include <swdtflvr.hxx> +#include <rootfrm.hxx> +#include <edtwin.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/profilezone.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <tools/UnitConversion.hxx> +#include <comphelper/dumpxmltostring.hxx> +#include <fmtanchr.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::frame; + +using ::com::sun::star::util::URL; + +SwXTextView::SwXTextView(SwView* pSwView) : + SwXTextView_Base(pSwView), + m_SelChangedListeners(m_aMutex), + m_pView(pSwView), + m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_VIEW ) ) +{ + +} + +SwXTextView::~SwXTextView() +{ + Invalidate(); +} + +void SwXTextView::Invalidate() +{ + if(mxViewSettings.is()) + { + mxViewSettings->Invalidate(); + mxViewSettings.clear(); + } + if(mxTextViewCursor.is()) + { + mxTextViewCursor->Invalidate(); + mxTextViewCursor.clear(); + } + + osl_atomic_increment(&m_refCount); //prevent second d'tor call + + { + uno::Reference<uno::XInterface> const xInt(static_cast< + cppu::OWeakObject*>(static_cast<SfxBaseController*>(this))); + lang::EventObject aEvent(xInt); + m_SelChangedListeners.disposeAndClear(aEvent); + } + + osl_atomic_decrement(&m_refCount); + m_pView = nullptr; +} + +sal_Bool SwXTextView::select(const uno::Any& aInterface) +{ + SolarMutexGuard aGuard; + + uno::Reference< uno::XInterface > xInterface; + if (!GetView() || !(aInterface >>= xInterface)) + { + return false; + } + + SwWrtShell& rSh = GetView()->GetWrtShell(); + SwDoc* pDoc = GetView()->GetDocShell()->GetDoc(); + std::vector<SdrObject *> sdrObjects; + uno::Reference<awt::XControlModel> const xCtrlModel(xInterface, + UNO_QUERY); + if (xCtrlModel.is()) + { + uno::Reference<awt::XControl> xControl; + SdrObject *const pSdrObject = GetControl(xCtrlModel, xControl); + if (pSdrObject) // hmm... needs view to verify it's in right doc... + { + sdrObjects.push_back(pSdrObject); + } + } + else + { + SwPaM * pPaM(nullptr); + std::pair<OUString, FlyCntType> frame; + OUString tableName; + SwUnoTableCursor const* pTableCursor(nullptr); + ::sw::mark::IMark const* pMark(nullptr); + SwUnoCursorHelper::GetSelectableFromAny(xInterface, *pDoc, + pPaM, frame, tableName, pTableCursor, pMark, sdrObjects); + if (pPaM) + { + rSh.EnterStdMode(); + rSh.SetSelection(*pPaM); + // the pPaM has been copied - delete it + while (pPaM->GetNext() != pPaM) + { + // coverity[deref_arg] - the SwPaM delete moves a new entry into GetNext() + delete pPaM->GetNext(); + } + delete pPaM; + return true; + } + else if (!frame.first.isEmpty()) + { + bool const bSuccess(rSh.GotoFly(frame.first, frame.second)); + if (bSuccess) + { + rSh.HideCursor(); + rSh.EnterSelFrameMode(); + } + return true; + } + else if (!tableName.isEmpty()) + { + rSh.EnterStdMode(); + rSh.GotoTable(tableName); + return true; + } + else if (pTableCursor) + { + UnoActionRemoveContext const aContext(*pTableCursor); + rSh.EnterStdMode(); + rSh.SetSelection(*pTableCursor); + return true; + } + else if (pMark) + { + rSh.EnterStdMode(); + rSh.GotoMark(pMark); + return true; + } + // sdrObjects handled below + } + bool bRet(false); + if (!sdrObjects.empty()) + { + + SdrView *const pDrawView = rSh.GetDrawView(); + SdrPageView *const pPV = pDrawView->GetSdrPageView(); + + pDrawView->SdrEndTextEdit(); + pDrawView->UnmarkAll(); + + for (SdrObject* pSdrObject : sdrObjects) + { + // GetSelectableFromAny did not check pSdrObject is in right doc! + if (pPV && pSdrObject->getSdrPageFromSdrObject() == pPV->GetPage()) + { + pDrawView->MarkObj(pSdrObject, pPV); + bRet = true; + } + } + + // tdf#112696 if we selected every individual element of a group, then + // select that group instead + const SdrMarkList &rMrkList = pDrawView->GetMarkedObjectList(); + size_t nMarkCount = rMrkList.GetMarkCount(); + if (nMarkCount > 1) + { + SdrObject* pObject = rMrkList.GetMark(0)->GetMarkedSdrObj(); + SdrObject* pGroupParent = pObject->getParentSdrObjectFromSdrObject(); + for (size_t i = 1; i < nMarkCount; ++i) + { + pObject = rMrkList.GetMark(i)->GetMarkedSdrObj(); + SdrObject* pParent = pObject->getParentSdrObjectFromSdrObject(); + if (pParent != pGroupParent) + { + pGroupParent = nullptr; + break; + } + } + + if (pGroupParent && pGroupParent->IsGroupObject() && + pGroupParent->getChildrenOfSdrObject()->GetObjCount() == nMarkCount) + { + pDrawView->UnmarkAll(); + pDrawView->MarkObj(pGroupParent, pPV); + } + } + } + return bRet; +} + +uno::Any SwXTextView::getSelection() +{ + SolarMutexGuard aGuard; + uno::Reference< uno::XInterface > aRef; + if(GetView()) + { + //force immediat shell update + m_pView->StopShellTimer(); + //Generating an interface from the current selection. + SwWrtShell& rSh = m_pView->GetWrtShell(); + ShellMode eSelMode = m_pView->GetShellMode(); + switch(eSelMode) + { + case ShellMode::TableText : + { + if(rSh.GetTableCursor()) + { + OSL_ENSURE(rSh.GetTableFormat(), "not a table format?"); + uno::Reference< text::XTextTableCursor > xCursor = new SwXTextTableCursor(*rSh.GetTableFormat(), + rSh.GetTableCursor()); + aRef.set(xCursor, uno::UNO_QUERY); + break; + } + [[fallthrough]]; + // without a table selection the text will be delivered + } + case ShellMode::ListText : + case ShellMode::TableListText: + case ShellMode::Text : + { + uno::Reference< container::XIndexAccess > xPos = SwXTextRanges::Create(rSh.GetCursor()); + aRef.set(xPos, uno::UNO_QUERY); + } + break; + case ShellMode::Frame : + { + SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat(); + if (pFormat) + { + aRef = cppu::getXWeak(SwXTextFrame::CreateXTextFrame( + *pFormat->GetDoc(), pFormat).get()); + } + } + break; + case ShellMode::Graphic : + { + SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat(); + if (pFormat) + { + aRef = cppu::getXWeak(SwXTextGraphicObject::CreateXTextGraphicObject( + *pFormat->GetDoc(), pFormat).get()); + } + } + break; + case ShellMode::Object : + { + SwFrameFormat *const pFormat = rSh.GetFlyFrameFormat(); + if (pFormat) + { + aRef = cppu::getXWeak(SwXTextEmbeddedObject::CreateXTextEmbeddedObject( + *pFormat->GetDoc(), pFormat).get()); + } + } + break; + case ShellMode::Draw : + case ShellMode::DrawForm : + case ShellMode::DrawText : + case ShellMode::Bezier : + { + uno::Reference< drawing::XShapes > xShCol = drawing::ShapeCollection::create( + comphelper::getProcessComponentContext()); + + const SdrMarkList& rMarkList = rSh.GetDrawView()->GetMarkedObjectList(); + for(size_t i = 0; i < rMarkList.GetMarkCount(); ++i) + { + SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + uno::Reference<drawing::XShape> xShape = SwFmDrawPage::GetShape( pObj ); + xShCol->add(xShape); + } + aRef.set(xShCol, uno::UNO_QUERY); + } + break; + default:;//prevent warning + } + } + uno::Any aRet(&aRef, cppu::UnoType<uno::XInterface>::get()); + return aRet; +} + +void SwXTextView::addSelectionChangeListener( + const uno::Reference< view::XSelectionChangeListener > & rxListener) +{ + SolarMutexGuard aGuard; + m_SelChangedListeners.addInterface(rxListener); +} + +void SwXTextView::removeSelectionChangeListener( + const uno::Reference< view::XSelectionChangeListener > & rxListener) +{ + SolarMutexGuard aGuard; + m_SelChangedListeners.removeInterface(rxListener); +} + +SdrObject* SwXTextView::GetControl( + const uno::Reference< awt::XControlModel > & xModel, + uno::Reference< awt::XControl >& xToFill ) +{ + SwView* pView2 = GetView(); + FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr; + SdrView* pDrawView = pView2 ? pView2->GetDrawView() : nullptr; + vcl::Window* pWindow = pView2 ? pView2->GetWrtShell().GetWin() : nullptr; + + OSL_ENSURE( pFormShell && pDrawView && pWindow, "SwXTextView::GetControl: how could I?" ); + + SdrObject* pControl = nullptr; + if ( pFormShell && pDrawView && pWindow ) + pControl = pFormShell->GetFormControl( xModel, *pDrawView, *pWindow->GetOutDev(), xToFill ); + return pControl; +} + +uno::Reference< awt::XControl > SwXTextView::getControl(const uno::Reference< awt::XControlModel > & xModel) +{ + SolarMutexGuard aGuard; + uno::Reference< awt::XControl > xRet; + GetControl(xModel, xRet); + return xRet; +} + +uno::Reference< form::runtime::XFormController > SAL_CALL SwXTextView::getFormController( const uno::Reference< form::XForm >& Form ) +{ + SolarMutexGuard aGuard; + + SwView* pView2 = GetView(); + FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr; + SdrView* pDrawView = pView2 ? pView2->GetDrawView() : nullptr; + vcl::Window* pWindow = pView2 ? pView2->GetWrtShell().GetWin() : nullptr; + OSL_ENSURE( pFormShell && pDrawView && pWindow, "SwXTextView::getFormController: how could I?" ); + + uno::Reference< form::runtime::XFormController > xController; + if ( pFormShell && pDrawView && pWindow ) + xController = FmFormShell::GetFormController( Form, *pDrawView, *pWindow->GetOutDev() ); + return xController; +} + +sal_Bool SAL_CALL SwXTextView::isFormDesignMode( ) +{ + SolarMutexGuard aGuard; + SwView* pView2 = GetView(); + FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr; + return !pFormShell || pFormShell->IsDesignMode(); +} + +void SAL_CALL SwXTextView::setFormDesignMode( sal_Bool DesignMode ) +{ + SolarMutexGuard aGuard; + SwView* pView2 = GetView(); + FmFormShell* pFormShell = pView2 ? pView2->GetFormShell() : nullptr; + if ( pFormShell ) + pFormShell->SetDesignMode( DesignMode ); +} + +uno::Reference< text::XTextViewCursor > SwXTextView::getViewCursor() +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("getViewCursor"); + if(!GetView()) + throw uno::RuntimeException(); + + if(!mxTextViewCursor.is()) + { + mxTextViewCursor = new SwXTextViewCursor(GetView()); + } + return mxTextViewCursor; +} + +uno::Reference<text::XTextRange> +SwXTextView::createTextRangeByPixelPosition(const awt::Point& rPixelPosition) +{ + SolarMutexGuard aGuard; + + Point aPixelPoint(rPixelPosition.X, rPixelPosition.Y); + if (!m_pView) + throw RuntimeException(); + + Point aLogicPoint = m_pView->GetEditWin().PixelToLogic(aPixelPoint); + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPosition aPosition(*rSh.GetCurrentShellCursor().GetPoint()); + rSh.GetLayout()->GetModelPositionForViewPoint(&aPosition, aLogicPoint); + + if (aPosition.GetNode().IsGrfNode()) + { + // The point is closest to a graphic node, look up its format. + const SwFrameFormat* pGraphicFormat = aPosition.GetNode().GetFlyFormat(); + if (pGraphicFormat) + { + // Get the anchor of this format. + const SwFormatAnchor& rAnchor = pGraphicFormat->GetAnchor(); + const SwPosition* pAnchor = rAnchor.GetContentAnchor(); + if (pAnchor) + { + aPosition = *pAnchor; + } + else + { + // Page-anchored graphics have no anchor. + return {}; + } + } + } + + rtl::Reference<SwXTextRange> xRet + = SwXTextRange::CreateXTextRange(*rSh.GetDoc(), aPosition, /*pMark=*/nullptr); + + return xRet; +} + +uno::Reference< beans::XPropertySet > SwXTextView::getViewSettings() +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw uno::RuntimeException(); + + if(!mxViewSettings.is()) + { + mxViewSettings = new SwXViewSettings( m_pView ); + } + + return mxViewSettings; +} + +Sequence< Sequence< PropertyValue > > SwXTextView::getRubyList( sal_Bool /*bAutomatic*/ ) +{ + SolarMutexGuard aGuard; + + if(!GetView()) + throw RuntimeException(); + SwWrtShell& rSh = m_pView->GetWrtShell(); + ShellMode eSelMode = m_pView->GetShellMode(); + if (eSelMode != ShellMode::ListText && + eSelMode != ShellMode::TableListText && + eSelMode != ShellMode::TableText && + eSelMode != ShellMode::Text ) + return Sequence< Sequence< PropertyValue > > (); + + SwRubyList aList; + + const sal_uInt16 nCount = SwDoc::FillRubyList( *rSh.GetCursor(), aList ); + Sequence< Sequence< PropertyValue > > aRet(nCount); + Sequence< PropertyValue >* pRet = aRet.getArray(); + OUString aString; + for(sal_uInt16 n = 0; n < nCount; n++) + { + const SwRubyListEntry* pEntry = aList[n].get(); + + const OUString& rEntryText = pEntry->GetText(); + const SwFormatRuby& rAttr = pEntry->GetRubyAttr(); + + pRet[n].realloc(6); + PropertyValue* pValues = pRet[n].getArray(); + pValues[0].Name = UNO_NAME_RUBY_BASE_TEXT; + pValues[0].Value <<= rEntryText; + pValues[1].Name = UNO_NAME_RUBY_TEXT; + pValues[1].Value <<= rAttr.GetText(); + pValues[2].Name = UNO_NAME_RUBY_CHAR_STYLE_NAME; + SwStyleNameMapper::FillProgName(rAttr.GetCharFormatName(), aString, SwGetPoolIdFromName::ChrFmt ); + pValues[2].Value <<= aString; + pValues[3].Name = UNO_NAME_RUBY_ADJUST; + pValues[3].Value <<= static_cast<sal_Int16>(rAttr.GetAdjustment()); + pValues[4].Name = UNO_NAME_RUBY_IS_ABOVE; + pValues[4].Value <<= !rAttr.GetPosition(); + pValues[5].Name = UNO_NAME_RUBY_POSITION; + pValues[5].Value <<= rAttr.GetPosition(); + } + return aRet; +} + +void SAL_CALL SwXTextView::setRubyList( + const Sequence< Sequence< PropertyValue > >& rRubyList, sal_Bool /*bAutomatic*/ ) +{ + SolarMutexGuard aGuard; + + if(!GetView() || !rRubyList.hasElements()) + throw RuntimeException(); + SwWrtShell& rSh = m_pView->GetWrtShell(); + ShellMode eSelMode = m_pView->GetShellMode(); + if (eSelMode != ShellMode::ListText && + eSelMode != ShellMode::TableListText && + eSelMode != ShellMode::TableText && + eSelMode != ShellMode::Text ) + throw RuntimeException(); + + SwRubyList aList; + + for(const Sequence<PropertyValue>& rPropList : rRubyList) + { + std::unique_ptr<SwRubyListEntry> pEntry(new SwRubyListEntry); + OUString sTmp; + for(const PropertyValue& rProperty : rPropList) + { + if(rProperty.Name == UNO_NAME_RUBY_BASE_TEXT) + { + rProperty.Value >>= sTmp; + pEntry->SetText(sTmp); + } + else if(rProperty.Name == UNO_NAME_RUBY_TEXT) + { + rProperty.Value >>= sTmp; + pEntry->GetRubyAttr().SetText(sTmp); + } + else if(rProperty.Name == UNO_NAME_RUBY_CHAR_STYLE_NAME) + { + if(rProperty.Value >>= sTmp) + { + OUString sName; + SwStyleNameMapper::FillUIName(sTmp, sName, SwGetPoolIdFromName::ChrFmt ); + const sal_uInt16 nPoolId = sName.isEmpty() ? 0 + : SwStyleNameMapper::GetPoolIdFromUIName(sName, + SwGetPoolIdFromName::ChrFmt ); + + pEntry->GetRubyAttr().SetCharFormatName( sName ); + pEntry->GetRubyAttr().SetCharFormatId( nPoolId ); + } + } + else if(rProperty.Name == UNO_NAME_RUBY_ADJUST) + { + sal_Int16 nTmp = 0; + if(rProperty.Value >>= nTmp) + pEntry->GetRubyAttr().SetAdjustment(static_cast<css::text::RubyAdjust>(nTmp)); + } + else if(rProperty.Name == UNO_NAME_RUBY_IS_ABOVE) + { + bool bValue = !rProperty.Value.hasValue() || + *o3tl::doAccess<bool>(rProperty.Value); + pEntry->GetRubyAttr().SetPosition(bValue ? 0 : 1); + } + else if(rProperty.Name == UNO_NAME_RUBY_POSITION) + { + sal_Int16 nTmp = 0; + if(rProperty.Value >>= nTmp) + pEntry->GetRubyAttr().SetPosition( nTmp ); + } + } + aList.push_back(std::move(pEntry)); + } + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + pDoc->SetRubyList( *rSh.GetCursor(), aList ); +} + +SfxObjectShellLock SwXTextView::BuildTmpSelectionDoc() +{ + SwWrtShell& rOldSh = m_pView->GetWrtShell(); + SfxPrinter *pPrt = rOldSh.getIDocumentDeviceAccess().getPrinter( false ); + SwDocShell* pDocSh; + SfxObjectShellLock xDocSh( pDocSh = new SwDocShell(SfxObjectCreateMode::STANDARD) ); + xDocSh->DoInitNew(); + SwDoc *const pTempDoc( pDocSh->GetDoc() ); + // #i103634#, #i112425#: do not expand numbering and fields on PDF export + pTempDoc->SetClipBoard(true); + rOldSh.FillPrtDoc(*pTempDoc, pPrt); + SfxViewFrame* pDocFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, SFX_INTERFACE_NONE ); + SwView* pDocView = static_cast<SwView*>( pDocFrame->GetViewShell() ); + pDocView->AttrChangedNotify(nullptr);//So that SelectShell is called. + if (SwWrtShell* pSh = pDocView->GetWrtShellPtr()) + { + IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess(); + SfxPrinter* pTempPrinter = rIDDA.getPrinter( true ); + + const SwPageDesc& rCurPageDesc = rOldSh.GetPageDesc(rOldSh.GetCurPageDesc()); + + IDocumentDeviceAccess& rIDDA_old = rOldSh.getIDocumentDeviceAccess(); + + if( rIDDA_old.getPrinter( false ) ) + { + rIDDA.setJobsetup( *rIDDA_old.getJobsetup() ); + //#69563# if it isn't the same printer then the pointer has been invalidated! + pTempPrinter = rIDDA.getPrinter( true ); + } + + pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue()); + } + + return xDocSh; +} + +void SwXTextView::NotifySelChanged() +{ + OSL_ENSURE( m_pView, "view is missing" ); + + lang::EventObject const aEvent(getXWeak()); + m_SelChangedListeners.notifyEach( + &view::XSelectionChangeListener::selectionChanged, aEvent); +} + +void SwXTextView::NotifyDBChanged() +{ + URL aURL; + aURL.Complete = OUString::createFromAscii(SwXDispatch::GetDBChangeURL()); + + m_SelChangedListeners.forEach( + [&aURL] (const uno::Reference<XSelectionChangeListener>& xListener) + { + uno::Reference<XDispatch> xDispatch(xListener, UNO_QUERY); + if (xDispatch) + xDispatch->dispatch(aURL, {}); + }); +} + +uno::Reference< beans::XPropertySetInfo > SAL_CALL SwXTextView::getPropertySetInfo( ) +{ + SolarMutexGuard aGuard; + static uno::Reference< XPropertySetInfo > aRef = m_pPropSet->getPropertySetInfo(); + return aRef; +} + +void SAL_CALL SwXTextView::setPropertyValue( + const OUString& rPropertyName, const uno::Any& rValue ) +{ + SolarMutexGuard aGuard; + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pEntry) + throw UnknownPropertyException(rPropertyName); + else if (pEntry->nFlags & PropertyAttribute::READONLY) + throw PropertyVetoException(); + else + { + switch (pEntry->nWID) + { + case WID_IS_HIDE_SPELL_MARKS : + // deprecated #i91949 + break; + case WID_IS_CONSTANT_SPELLCHECK : + { + bool bVal = false; + const SwViewOption *pOpt = m_pView->GetWrtShell().GetViewOptions(); + if (!pOpt || !(rValue >>= bVal)) + throw RuntimeException(); + SwViewOption aNewOpt( *pOpt ); + if (pEntry->nWID == WID_IS_CONSTANT_SPELLCHECK) + aNewOpt.SetOnlineSpell(bVal); + m_pView->GetWrtShell().ApplyViewOptions( aNewOpt ); + } + break; + default : + OSL_FAIL("unknown WID"); + } + } +} + +uno::Any SAL_CALL SwXTextView::getPropertyValue( + const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + + Any aRet; + + const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName ); + if (!pEntry) + throw UnknownPropertyException(rPropertyName); + + sal_Int16 nWID = pEntry->nWID; + switch (nWID) + { + case WID_PAGE_COUNT : + case WID_LINE_COUNT : + { + // format document completely in order to get meaningful + // values for page count and line count + m_pView->GetWrtShell().CalcLayout(); + + sal_Int32 nCount = -1; + if (nWID == WID_PAGE_COUNT) + nCount = m_pView->GetWrtShell().GetPageCount(); + else // WID_LINE_COUNT + nCount = m_pView->GetWrtShell().GetLineCount(); + aRet <<= nCount; + } + break; + case WID_IS_HIDE_SPELL_MARKS : + // deprecated #i91949 + break; + case WID_IS_CONSTANT_SPELLCHECK : + { + const SwViewOption *pOpt = m_pView->GetWrtShell().GetViewOptions(); + if (!pOpt) + throw RuntimeException(); + aRet <<= pOpt->IsOnlineSpell(); + } + break; + default : + OSL_FAIL("unknown WID"); + } + + return aRet; +} + +void SAL_CALL SwXTextView::addPropertyChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener >& /*rxListener*/ ) +{ + OSL_FAIL("not implemented"); +} + +void SAL_CALL SwXTextView::removePropertyChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener >& /*rxListener*/ ) +{ + OSL_FAIL("not implemented"); +} + +void SAL_CALL SwXTextView::addVetoableChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*rxListener*/ ) +{ + OSL_FAIL("not implemented"); +} + +void SAL_CALL SwXTextView::removeVetoableChangeListener( + const OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener >& /*rxListener*/ ) +{ + OSL_FAIL("not implemented"); +} + +OUString SwXTextView::getImplementationName() +{ + return "SwXTextView"; +} + +sal_Bool SwXTextView::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXTextView::getSupportedServiceNames() +{ + return { "com.sun.star.text.TextDocumentView", "com.sun.star.view.OfficeDocumentView" }; +} + +SwXTextViewCursor::SwXTextViewCursor(SwView* pVw) : + m_pView(pVw), + m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_CURSOR)) +{ +} + +SwXTextViewCursor::~SwXTextViewCursor() +{ +} + +// used to determine if there is a text selection or not. +// If there is no text selection the functions that need a working +// cursor will be disabled (throw RuntimeException). This will be the case +// for the following interfaces: +// - XViewCursor +// - XTextCursor +// - XTextRange +// - XLineCursor +bool SwXTextViewCursor::IsTextSelection( bool bAllowTables ) const +{ + + bool bRes = false; + OSL_ENSURE(m_pView, "m_pView is NULL ???"); + if(m_pView) + { + //! m_pView->GetShellMode() will only work after the shell + //! has already changed and thus can not be used here! + SelectionType eSelType = m_pView->GetWrtShell().GetSelectionType(); + bRes = ( (SelectionType::Text & eSelType) || + (SelectionType::NumberList & eSelType) ) && + (!(SelectionType::TableCell & eSelType) || bAllowTables); + } + return bRes; +} + +sal_Bool SwXTextViewCursor::isVisible() +{ + OSL_FAIL("not implemented"); + return true; +} + +void SwXTextViewCursor::setVisible(sal_Bool /*bVisible*/) +{ + OSL_FAIL("not implemented"); +} + +awt::Point SwXTextViewCursor::getPosition() +{ + SolarMutexGuard aGuard; + awt::Point aRet; + if(!m_pView) + throw uno::RuntimeException(); + + const SwWrtShell& rSh = m_pView->GetWrtShell(); + const SwRect& aCharRect(rSh.GetCharRect()); + + const SwFrameFormat& rMaster = rSh.GetPageDesc( rSh.GetCurPageDesc() ).GetMaster(); + + const SvxULSpaceItem& rUL = rMaster.GetULSpace(); + const tools::Long nY = aCharRect.Top() - (rUL.GetUpper() + DOCUMENTBORDER); + aRet.Y = convertTwipToMm100(nY); + + const SvxLRSpaceItem& rLR = rMaster.GetLRSpace(); + const tools::Long nX = aCharRect.Left() - (rLR.GetLeft() + DOCUMENTBORDER); + aRet.X = convertTwipToMm100(nX); + + return aRet; +} + +void SwXTextViewCursor::collapseToStart() +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + if(rSh.HasSelection()) + { + SwPaM* pShellCursor = rSh.GetCursor(); + if(*pShellCursor->GetPoint() > *pShellCursor->GetMark()) + pShellCursor->Exchange(); + pShellCursor->DeleteMark(); + rSh.EnterStdMode(); + rSh.SetSelection(*pShellCursor); + } + +} + +void SwXTextViewCursor::collapseToEnd() +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + if(rSh.HasSelection()) + { + SwPaM* pShellCursor = rSh.GetCursor(); + if(*pShellCursor->GetPoint() < *pShellCursor->GetMark()) + pShellCursor->Exchange(); + pShellCursor->DeleteMark(); + rSh.EnterStdMode(); + rSh.SetSelection(*pShellCursor); + } + +} + +sal_Bool SwXTextViewCursor::isCollapsed() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + const SwWrtShell& rSh = m_pView->GetWrtShell(); + bRet = !rSh.HasSelection(); + + return bRet; + +} + +sal_Bool SwXTextViewCursor::goLeft(sal_Int16 nCount, sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().Left( SwCursorSkipMode::Chars, bExpand, nCount, true ); + + return bRet; +} + +sal_Bool SwXTextViewCursor::goRight(sal_Int16 nCount, sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().Right( SwCursorSkipMode::Chars, bExpand, nCount, true ); + + return bRet; + +} + +void SwXTextViewCursor::gotoRange( + const uno::Reference< text::XTextRange > & xRange, + sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + if(!(m_pView && xRange.is())) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwUnoInternalPaM rDestPam(*m_pView->GetDocShell()->GetDoc()); + if (!::sw::XTextRangeToSwPaM(rDestPam, xRange)) + { + throw uno::RuntimeException(); + } + + ShellMode eSelMode = m_pView->GetShellMode(); + SwWrtShell& rSh = m_pView->GetWrtShell(); + // call EnterStdMode in non-text selections only + if(!bExpand || + (eSelMode != ShellMode::TableText && + eSelMode != ShellMode::ListText && + eSelMode != ShellMode::TableListText && + eSelMode != ShellMode::Text )) + rSh.EnterStdMode(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwPaM aOwnPaM(*pShellCursor->GetPoint()); + if(pShellCursor->HasMark()) + { + aOwnPaM.SetMark(); + *aOwnPaM.GetMark() = *pShellCursor->GetMark(); + } + + SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xRange.get()); + SwXParagraph* pPara = dynamic_cast<SwXParagraph*>(xRange.get()); + OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xRange.get()); + + const FrameTypeFlags nFrameType = rSh.GetFrameType(nullptr,true); + + SwStartNodeType eSearchNodeType = SwNormalStartNode; + if(nFrameType & FrameTypeFlags::FLY_ANY) + eSearchNodeType = SwFlyStartNode; + else if(nFrameType &FrameTypeFlags::HEADER) + eSearchNodeType = SwHeaderStartNode; + else if(nFrameType & FrameTypeFlags::FOOTER) + eSearchNodeType = SwFooterStartNode; + else if(nFrameType & FrameTypeFlags::TABLE) + eSearchNodeType = SwTableBoxStartNode; + else if(nFrameType & FrameTypeFlags::FOOTNOTE) + eSearchNodeType = SwFootnoteStartNode; + + const SwStartNode* pOwnStartNode = aOwnPaM.GetPointNode(). + FindSttNodeByType(eSearchNodeType); + + const SwNode* pSrcNode = nullptr; + if(pCursor && pCursor->GetPaM()) + { + pSrcNode = &pCursor->GetPaM()->GetPointNode(); + } + else if (pRange) + { + SwPaM aPam(pRange->GetDoc().GetNodes()); + if (pRange->GetPositions(aPam)) + { + pSrcNode = &aPam.GetPointNode(); + } + } + else if (pPara && pPara->GetTextNode()) + { + pSrcNode = pPara->GetTextNode(); + } + const SwStartNode* pTmp = pSrcNode ? pSrcNode->FindSttNodeByType(eSearchNodeType) : nullptr; + + //Skip SectionNodes + while(pTmp && pTmp->IsSectionNode()) + { + pTmp = pTmp->StartOfSectionNode(); + } + while(pOwnStartNode && pOwnStartNode->IsSectionNode()) + { + pOwnStartNode = pOwnStartNode->StartOfSectionNode(); + } + //Without Expand it is allowed to jump out with the ViewCursor everywhere, + //with Expand only in the same environment + if(bExpand && + (pOwnStartNode != pTmp || + (eSelMode != ShellMode::TableText && + eSelMode != ShellMode::ListText && + eSelMode != ShellMode::TableListText && + eSelMode != ShellMode::Text))) + throw uno::RuntimeException(); + + //Now, the selection must be expanded. + if(bExpand) + { + // The cursor should include everything that has been included + // by him and the transferred Range. + SwPosition aOwnLeft(*aOwnPaM.Start()); + SwPosition aOwnRight(*aOwnPaM.End()); + auto [pParamLeft, pParamRight] = rDestPam.StartEnd(); // SwPosition* + // Now four SwPositions are there, two of them are needed, but which? + if(aOwnRight > *pParamRight) + *aOwnPaM.GetPoint() = aOwnRight; + else + *aOwnPaM.GetPoint() = *pParamRight; + aOwnPaM.SetMark(); + if(aOwnLeft < *pParamLeft) + *aOwnPaM.GetMark() = aOwnLeft; + else + *aOwnPaM.GetMark() = *pParamLeft; + } + else + { + //The cursor shall match the passed range. + *aOwnPaM.GetPoint() = *rDestPam.GetPoint(); + if(rDestPam.HasMark()) + { + aOwnPaM.SetMark(); + *aOwnPaM.GetMark() = *rDestPam.GetMark(); + } + else + aOwnPaM.DeleteMark(); + } + rSh.SetSelection(aOwnPaM); + + +} + +void SwXTextViewCursor::gotoStart(sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SwXTextViewCursor::gotoStart"); + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + m_pView->GetWrtShell().StartOfSection( bExpand ); + +} + +void SwXTextViewCursor::gotoEnd(sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SwXTextViewCursor::gotoEnd"); + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + m_pView->GetWrtShell().EndOfSection( bExpand ); + +} + +sal_Bool SwXTextViewCursor::jumpToFirstPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + if (rSh.IsSelFrameMode()) + { + rSh.UnSelectFrame(); + rSh.LeaveSelFrameMode(); + } + rSh.EnterStdMode(); + bRet = rSh.SttEndDoc(true); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToLastPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + if (rSh.IsSelFrameMode()) + { + rSh.UnSelectFrame(); + rSh.LeaveSelFrameMode(); + } + rSh.EnterStdMode(); + bRet = rSh.SttEndDoc(false); + rSh.SttPg(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToPage(sal_Int16 nPage) +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + bRet = m_pView->GetWrtShell().GotoPage(nPage, true); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToNextPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + bRet = m_pView->GetWrtShell().SttNxtPg(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToPreviousPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + bRet = m_pView->GetWrtShell().EndPrvPg(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToEndOfPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + bRet = m_pView->GetWrtShell().EndPg(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::jumpToStartOfPage() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + bRet = m_pView->GetWrtShell().SttPg(); + + return bRet; +} + +sal_Int16 SwXTextViewCursor::getPage() +{ + SolarMutexGuard aGuard; + sal_Int16 nRet = 0; + if(!m_pView) + throw uno::RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + nRet = static_cast<sal_Int16>(pShellCursor->GetPageNum()); + + return nRet; +} + +sal_Bool SwXTextViewCursor::screenDown() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + SfxRequest aReq(FN_PAGEDOWN, SfxCallMode::SLOT, m_pView->GetPool()); + m_pView->Execute(aReq); + const SfxPoolItemHolder& rResult(aReq.GetReturnValue()); + bRet = nullptr != rResult.getItem() && static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::screenUp() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + SfxRequest aReq(FN_PAGEUP, SfxCallMode::SLOT, m_pView->GetPool()); + m_pView->Execute(aReq); + const SfxPoolItemHolder& rResult(aReq.GetReturnValue()); + bRet = nullptr != rResult.getItem() && static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue(); + + return bRet; +} + +uno::Reference< text::XText > SwXTextViewCursor::getText() +{ + SolarMutexGuard aGuard; + uno::Reference< text::XText > xRet; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + xRet = ::sw::CreateParentXText(*pDoc, *pShellCursor->Start()); + + return xRet; +} + +uno::Reference< text::XTextRange > SwXTextViewCursor::getStart() +{ + SolarMutexGuard aGuard; + uno::Reference< text::XTextRange > xRet; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + xRet = SwXTextRange::CreateXTextRange(*pDoc, *pShellCursor->Start(), nullptr); + + return xRet; +} + +uno::Reference< text::XTextRange > SwXTextViewCursor::getEnd() +{ + SolarMutexGuard aGuard; + rtl::Reference<SwXTextRange> xRet; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + xRet = SwXTextRange::CreateXTextRange(*pDoc, *pShellCursor->End(), nullptr); + + return xRet; +} + +OUString SwXTextViewCursor::getString() +{ + SolarMutexGuard aGuard; + OUString uRet; + if(m_pView) + { + if (!IsTextSelection( false )) + { + SAL_WARN("sw.uno", "no text selection in getString() " << getXWeak()); + return uRet; + } + + ShellMode eSelMode = m_pView->GetShellMode(); + switch(eSelMode) + { + //! since setString for SEL_TABLE_TEXT (with possible + //! multi selection of cells) would not work properly we + //! will ignore this case for both + //! functions (setString AND getString) because of symmetrie. + + case ShellMode::ListText : + case ShellMode::TableListText: + case ShellMode::Text : + { + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet, + rSh.GetLayout()); + break; + } + default:;//prevent warning + } + } + return uRet; +} + +void SwXTextViewCursor::setString(const OUString& aString) +{ + SolarMutexGuard aGuard; + if(!m_pView) + return; + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + ShellMode eSelMode = m_pView->GetShellMode(); + switch(eSelMode) + { + //! since setString for SEL_TABLE_TEXT (with possible + //! multi selection of cells) would not work properly we + //! will ignore this case for both + //! functions (setString AND getString) because of symmetrie. + + case ShellMode::ListText : + case ShellMode::TableListText : + case ShellMode::Text : + { + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwCursor* pShellCursor = rSh.GetCursor(); + SwUnoCursorHelper::SetString(*pShellCursor, aString); + break; + } + default:;//prevent warning + } +} + +uno::Reference< XPropertySetInfo > SwXTextViewCursor::getPropertySetInfo( ) +{ + static uno::Reference< XPropertySetInfo > xRef = m_pPropSet->getPropertySetInfo(); + return xRef; +} + +void SwXTextViewCursor::setPropertyValue( const OUString& rPropertyName, const Any& aValue ) +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwNode& rNode = pShellCursor->GetPointNode(); + if (!rNode.IsTextNode()) + throw RuntimeException(); + + SwUnoCursorHelper::SetPropertyValue( + *pShellCursor, *m_pPropSet, rPropertyName, aValue ); + + +} + +Any SwXTextViewCursor::getPropertyValue( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + Any aRet; + if(!m_pView) + throw RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + aRet = SwUnoCursorHelper::GetPropertyValue( + *pShellCursor, *m_pPropSet, rPropertyName); + + return aRet; +} + +void SwXTextViewCursor::addPropertyChangeListener( + const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ ) +{ +} + +void SwXTextViewCursor::removePropertyChangeListener( + const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ ) +{ +} + +void SwXTextViewCursor::addVetoableChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) +{ +} + +void SwXTextViewCursor::removeVetoableChangeListener( + const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) +{ +} + +PropertyState SwXTextViewCursor::getPropertyState( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + PropertyState eState; + if(!m_pView) + throw RuntimeException(); + + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + eState = SwUnoCursorHelper::GetPropertyState( + *pShellCursor, *m_pPropSet, rPropertyName); + + return eState; +} + +Sequence< PropertyState > SwXTextViewCursor::getPropertyStates( + const Sequence< OUString >& rPropertyNames ) +{ + SolarMutexGuard aGuard; + Sequence< PropertyState > aRet; + if(m_pView) + { + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + aRet = SwUnoCursorHelper::GetPropertyStates( + *pShellCursor, *m_pPropSet, rPropertyNames); + } + return aRet; +} + +void SwXTextViewCursor::setPropertyToDefault( const OUString& rPropertyName ) +{ + SolarMutexGuard aGuard; + if(m_pView) + { + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + SwUnoCursorHelper::SetPropertyToDefault( + *pShellCursor, *m_pPropSet, rPropertyName); + } +} + +Any SwXTextViewCursor::getPropertyDefault( const OUString& rPropertyName ) +{ + Any aRet; + SolarMutexGuard aGuard; + if(m_pView) + { + SwWrtShell& rSh = m_pView->GetWrtShell(); + SwPaM* pShellCursor = rSh.GetCursor(); + aRet = SwUnoCursorHelper::GetPropertyDefault( + *pShellCursor, *m_pPropSet, rPropertyName); + } + return aRet; +} + +sal_Bool SwXTextViewCursor::goDown(sal_Int16 nCount, sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SwXTextViewCursor::goDown"); + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().Down( bExpand, nCount, true ); + + return bRet; +} + +sal_Bool SwXTextViewCursor::goUp(sal_Int16 nCount, sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + comphelper::ProfileZone aZone("SwXTextViewCursor::goUp"); + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection()) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().Up( bExpand, nCount, true ); + + return bRet; +} + +sal_Bool SwXTextViewCursor::isAtStartOfLine() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().IsAtLeftMargin(); + + return bRet; +} + +sal_Bool SwXTextViewCursor::isAtEndOfLine() +{ + SolarMutexGuard aGuard; + bool bRet = false; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + bRet = m_pView->GetWrtShell().IsAtRightMargin(); + + return bRet; +} + +void SwXTextViewCursor::gotoEndOfLine(sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + m_pView->GetWrtShell().RightMargin(bExpand, true); + +} + +void SwXTextViewCursor::gotoStartOfLine(sal_Bool bExpand) +{ + SolarMutexGuard aGuard; + if(!m_pView) + throw uno::RuntimeException(); + + if (!IsTextSelection( false )) + throw uno::RuntimeException("no text selection", getXWeak() ); + + m_pView->GetWrtShell().LeftMargin(bExpand, true); + +} + +OUString SwXTextViewCursor::getImplementationName() +{ + return "SwXTextViewCursor"; +} + +sal_Bool SwXTextViewCursor::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SwXTextViewCursor::getSupportedServiceNames() +{ + return { "com.sun.star.text.TextViewCursor", + "com.sun.star.style.CharacterProperties", + "com.sun.star.style.CharacterPropertiesAsian", + "com.sun.star.style.CharacterPropertiesComplex", + "com.sun.star.style.ParagraphProperties", + "com.sun.star.style.ParagraphPropertiesAsian", + "com.sun.star.style.ParagraphPropertiesComplex" }; +} + +const SwDoc* SwXTextViewCursor::GetDoc() const +{ + SwWrtShell& rSh = m_pView->GetWrtShell(); + return rSh.GetCursor() ? &rSh.GetCursor()->GetDoc() : nullptr; +} + +SwDoc* SwXTextViewCursor::GetDoc() +{ + SwWrtShell& rSh = m_pView->GetWrtShell(); + return rSh.GetCursor() ? &rSh.GetCursor()->GetDoc() : nullptr; +} + +const SwPaM* SwXTextViewCursor::GetPaM() const +{ + SwWrtShell& rSh = m_pView->GetWrtShell(); + return rSh.GetCursor(); +} + +SwPaM* SwXTextViewCursor::GetPaM() +{ + SwWrtShell& rSh = m_pView->GetWrtShell(); + return rSh.GetCursor(); +} + +uno::Reference<datatransfer::XTransferable> SAL_CALL +SwXTextView::getTransferableForTextRange(uno::Reference<text::XTextRange> const& xTextRange) +{ + SolarMutexGuard aGuard; + + // the point is we can copy PaM that wouldn't be legal as shell cursor + SwUnoInternalPaM aPam(*m_pView->GetDocShell()->GetDoc()); + if (!::sw::XTextRangeToSwPaM(aPam, xTextRange, ::sw::TextRangeMode::AllowNonTextNode)) + { + throw uno::RuntimeException("invalid text range"); + } + + //force immediate shell update + GetView()->StopShellTimer(); + SwWrtShell& rSh = GetView()->GetWrtShell(); + rtl::Reference<SwTransferable> pTransfer = new SwTransferable(rSh); + const bool bLockedView = rSh.IsViewLocked(); + rSh.LockView( true ); + pTransfer->PrepareForCopyTextRange(aPam); + rSh.LockView( bLockedView ); + return pTransfer; +} + +OUString SAL_CALL SwXTextView::dump(const OUString& rKind) +{ + if (rKind == "layout") + { + SwRootFrame* pLayout = GetView()->GetWrtShell().GetLayout(); + return comphelper::dumpXmlToString([pLayout](xmlTextWriterPtr pWriter) + { pLayout->dumpAsXml(pWriter); }); + } + + return OUString(); +} + +uno::Reference< datatransfer::XTransferable > SAL_CALL SwXTextView::getTransferable() +{ + SolarMutexGuard aGuard; + + //force immediat shell update + GetView()->StopShellTimer(); + SwWrtShell& rSh = GetView()->GetWrtShell(); + if ( GetView()->GetShellMode() == ShellMode::DrawText ) + { + SdrView *pSdrView = rSh.GetDrawView(); + OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); + return pOLV->GetEditView().GetTransferable(); + } + else + { + rtl::Reference<SwTransferable> pTransfer = new SwTransferable( rSh ); + const bool bLockedView = rSh.IsViewLocked(); + rSh.LockView( true ); //lock visible section + pTransfer->PrepareForCopy(); + rSh.LockView( bLockedView ); + return pTransfer; + } +} + +void SAL_CALL SwXTextView::insertTransferable( const uno::Reference< datatransfer::XTransferable >& xTrans ) +{ + SolarMutexGuard aGuard; + + //force immediat shell update + GetView()->StopShellTimer(); + SwWrtShell& rSh = GetView()->GetWrtShell(); + if ( GetView()->GetShellMode() == ShellMode::DrawText ) + { + SdrView *pSdrView = rSh.GetDrawView(); + OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); + pOLV->GetEditView().InsertText( xTrans, GetView()->GetDocShell()->GetMedium()->GetBaseURL(), false ); + } + else + { + TransferableDataHelper aDataHelper( xTrans ); + if ( SwTransferable::IsPaste( rSh, aDataHelper ) ) + { + SwTransferable::Paste( rSh, aDataHelper ); + if( rSh.IsFrameSelected() || rSh.IsObjSelected() ) + rSh.EnterSelFrameMode(); + GetView()->AttrChangedNotify(nullptr); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |