Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dbinsdlg.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx

/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <dbinsdlg.hxx>
21
22#include <float.h>
23
24#include <hintids.hxx>
25#include <com/sun/star/container/XNameAccess.hpp>
26#include <com/sun/star/sdbc/XDataSource.hpp>
27#include <com/sun/star/sdbc/XRow.hpp>
28#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
29#include <com/sun/star/sdbcx/XRowLocate.hpp>
30#include <com/sun/star/sdb/XQueriesSupplier.hpp>
31#include <com/sun/star/sdb/XColumn.hpp>
32#include <com/sun/star/sdbc/DataType.hpp>
33#include <com/sun/star/beans/XPropertySet.hpp>
34#include <com/sun/star/util/NumberFormatter.hpp>
35#include <com/sun/star/util/XNumberFormatTypes.hpp>
36#include <comphelper/processfactory.hxx>
37#include <comphelper/sequence.hxx>
38#include <comphelper/types.hxx>
39#include <svl/numuno.hxx>
40#include <svl/stritem.hxx>
41#include <tools/diagnose_ex.h>
42#include <vcl/mnemonic.hxx>
43#include <svl/style.hxx>
44#include <svl/zformat.hxx>
45#include <sfx2/htmlmode.hxx>
46#include <svl/itemset.hxx>
47#include <editeng/brushitem.hxx>
48#include <editeng/boxitem.hxx>
49#include <unotools/collatorwrapper.hxx>
50#include <fmtclds.hxx>
51#include <tabcol.hxx>
52#include <uiitems.hxx>
53#include <viewopt.hxx>
54#include <wrtsh.hxx>
55#include <view.hxx>
56#include <docsh.hxx>
57#include <dbmgr.hxx>
58#include <tblafmt.hxx>
59#include <cellatr.hxx>
60#include <swtablerep.hxx>
61#include <dbfld.hxx>
62#include <fmtcol.hxx>
63#include <swwait.hxx>
64#include <modcfg.hxx>
65#include <swmodule.hxx>
66#include <poolfmt.hxx>
67#include <connectivity/dbtools.hxx>
68
69#include <cmdid.h>
70#include <SwStyleNameMapper.hxx>
71#include <tabsh.hxx>
72#include <swabstdlg.hxx>
73#include <strings.hrc>
74#include <IDocumentMarkAccess.hxx>
75
76#include <o3tl/any.hxx>
77
78#include <memory>
79#include <swuiexp.hxx>
80
81using namespace ::dbtools;
82using namespace ::com::sun::star;
83using namespace ::com::sun::star::beans;
84using namespace ::com::sun::star::container;
85using namespace ::com::sun::star::lang;
86using namespace ::com::sun::star::sdb;
87using namespace ::com::sun::star::sdbc;
88using namespace ::com::sun::star::sdbcx;
89using namespace ::com::sun::star::uno;
90
91const char cDBFieldStart = '<';
92const char cDBFieldEnd = '>';
93
94// Helper structure for adding database rows as fields or text
95struct DB_Column
96{
97 const enum class Type { FILLTEXT, COL_FIELD, COL_TEXT, SPLITPARA } eColType;
98
99 union {
100 OUString* pText;
101 SwField* pField;
102 sal_uInt32 nFormat;
103 };
104 const SwInsDBColumn* pColInfo;
105
106 DB_Column() : eColType(Type::SPLITPARA),
107 pText(nullptr),
108 pColInfo(nullptr)
109 {}
110
111 explicit DB_Column( const OUString& rText )
112 : eColType(Type::FILLTEXT),
113 pText(new OUString(rText)),
114 pColInfo(nullptr)
115 {}
116
117 DB_Column( const SwInsDBColumn& rInfo, sal_uInt32 nFormat_ )
118 : eColType(Type::COL_TEXT),
119 nFormat(nFormat_),
120 pColInfo(&rInfo)
121 {}
122
123 DB_Column( const SwInsDBColumn& rInfo, SwDBField& rField )
124 : eColType(Type::COL_FIELD),
125 pField(&rField),
126 pColInfo(&rInfo)
127 {}
128
129 ~DB_Column()
130 {
131 if( Type::COL_FIELD == eColType )
132 delete pField;
133 else if( Type::FILLTEXT == eColType )
134 delete pText;
135 }
136};
137
138namespace {
139
140struct DB_ColumnConfigData
141{
142 SwInsDBColumns aDBColumns;
143 OUString sEdit;
144 OUString sTableList;
145 OUString sTmplNm;
146 OUString sTAutoFormatNm;
147 bool bIsTable : 1,
148 bIsField : 1,
149 bIsHeadlineOn : 1,
150 bIsEmptyHeadln : 1;
151
152 DB_ColumnConfigData(DB_ColumnConfigData const&) = delete;
153 DB_ColumnConfigData& operator=(DB_ColumnConfigData const&) = delete;
154
155 DB_ColumnConfigData()
156 {
157 bIsTable = bIsHeadlineOn = true;
158 bIsField = bIsEmptyHeadln = false;
159 }
160};
161
162}
163
164bool SwInsDBColumn::operator<( const SwInsDBColumn& rCmp ) const
165{
166 return 0 > GetAppCollator().compareString( sColumn, rCmp.sColumn );
167}
168
169SwInsertDBColAutoPilot::SwInsertDBColAutoPilot( SwView& rView,
170 Reference<XDataSource> const & xDataSource,
171 Reference<sdbcx::XColumnsSupplier> const & xColSupp,
172 const SwDBData& rData )
173 : SfxDialogController(rView.GetWindow()->GetFrameWeld(), "modules/swriter/ui/insertdbcolumnsdialog.ui", "InsertDbColumnsDialog")
174 , ConfigItem("Office.Writer/InsertData/DataSet", ConfigItemMode::NONE)
175 , aDBData(rData)
176 , sNoTmpl(SwResId(SW_STR_NONEreinterpret_cast<char const *>("SW_STR_NONE" "\004" u8"[None]"
)
))
177 , pView(&rView)
178 , m_xRbAsTable(m_xBuilder->weld_radio_button("astable"))
179 , m_xRbAsField(m_xBuilder->weld_radio_button("asfields"))
180 , m_xRbAsText(m_xBuilder->weld_radio_button("astext"))
181 , m_xHeadFrame(m_xBuilder->weld_frame("dbframe"))
182 , m_xLbTableDbColumn(m_xBuilder->weld_tree_view("tabledbcols"))
183 , m_xLbTextDbColumn(m_xBuilder->weld_tree_view("tabletxtcols"))
184 , m_xFormatFrame(m_xBuilder->weld_frame("formatframe"))
185 , m_xRbDbFormatFromDb(m_xBuilder->weld_radio_button("fromdatabase"))
186 , m_xRbDbFormatFromUsr(m_xBuilder->weld_radio_button("userdefined"))
187 , m_xLbDbFormatFromUsr(new NumFormatListBox(m_xBuilder->weld_combo_box("numformat")))
188 , m_xIbDbcolToEdit(m_xBuilder->weld_button("toedit"))
189 , m_xEdDbText(m_xBuilder->weld_text_view("textview"))
190 , m_xFtDbParaColl(m_xBuilder->weld_label("parastylelabel"))
191 , m_xLbDbParaColl(m_xBuilder->weld_combo_box("parastyle"))
192 , m_xIbDbcolAllTo(m_xBuilder->weld_button("oneright"))
193 , m_xIbDbcolOneTo(m_xBuilder->weld_button("allright"))
194 , m_xIbDbcolOneFrom(m_xBuilder->weld_button("oneleft"))
195 , m_xIbDbcolAllFrom(m_xBuilder->weld_button("allleft"))
196 , m_xFtTableCol(m_xBuilder->weld_label("tablecolft"))
197 , m_xLbTableCol(m_xBuilder->weld_tree_view("tablecols"))
198 , m_xCbTableHeadon(m_xBuilder->weld_check_button("tableheading"))
199 , m_xRbHeadlColnms(m_xBuilder->weld_radio_button("columnname"))
200 , m_xRbHeadlEmpty(m_xBuilder->weld_radio_button("rowonly"))
201 , m_xPbTableFormat(m_xBuilder->weld_button("tableformat"))
202 , m_xPbTableAutofmt(m_xBuilder->weld_button("autoformat"))
203{
204 m_xEdDbText->set_size_request(m_xEdDbText->get_approximate_digit_width() * 40, -1);
205 m_xLbDbParaColl->make_sorted();
206
207 nGBFormatLen = m_xFormatFrame->get_label().getLength();
208
209 if (xColSupp.is())
210 {
211 SwWrtShell& rSh = pView->GetWrtShell();
212 SvNumberFormatter* pNumFormatr = rSh.GetNumberFormatter();
213 SvNumberFormatsSupplierObj* pNumFormat = new SvNumberFormatsSupplierObj( pNumFormatr );
214 Reference< util::XNumberFormatsSupplier > xDocNumFormatsSupplier = pNumFormat;
215 Reference< util::XNumberFormats > xDocNumberFormats = xDocNumFormatsSupplier->getNumberFormats();
216 Reference< util::XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, UNO_QUERY);
217
218 Reference<XPropertySet> xSourceProps(xDataSource, UNO_QUERY);
219 Reference< util::XNumberFormats > xNumberFormats;
220 if(xSourceProps.is())
221 {
222 Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
223 if(aFormats.hasValue())
224 {
225 Reference< util::XNumberFormatsSupplier> xSuppl;
226 aFormats >>= xSuppl;
227 if(xSuppl.is())
228 {
229 xNumberFormats = xSuppl->getNumberFormats( );
230 }
231 }
232 }
233 Reference <XNameAccess> xCols = xColSupp->getColumns();
234 const Sequence<OUString> aColNames = xCols->getElementNames();
235 for (const OUString& rColName : aColNames)
236 {
237 std::unique_ptr<SwInsDBColumn> pNew(new SwInsDBColumn( rColName ));
238 Any aCol = xCols->getByName(rColName);
239 Reference <XPropertySet> xCol;
240 aCol >>= xCol;
241 Any aType = xCol->getPropertyValue("Type");
242 sal_Int32 eDataType = 0;
243 aType >>= eDataType;
244 switch(eDataType)
245 {
246 case DataType::BIT:
247 case DataType::BOOLEAN:
248 case DataType::TINYINT:
249 case DataType::SMALLINT:
250 case DataType::INTEGER:
251 case DataType::BIGINT:
252 case DataType::FLOAT:
253 case DataType::REAL:
254 case DataType::DOUBLE:
255 case DataType::NUMERIC:
256 case DataType::DECIMAL:
257 case DataType::DATE:
258 case DataType::TIME:
259 case DataType::TIMESTAMP:
260 {
261 pNew->bHasFormat = true;
262 Any aFormat = xCol->getPropertyValue("FormatKey");
263 if(aFormat.hasValue())
264 {
265 sal_Int32 nFormat = 0;
266 aFormat >>= nFormat;
267 if(xNumberFormats.is())
268 {
269 try
270 {
271 Reference<XPropertySet> xNumProps = xNumberFormats->getByKey( nFormat );
272 Any aFormatVal = xNumProps->getPropertyValue("FormatString");
273 Any aLocale = xNumProps->getPropertyValue("Locale");
274 OUString sFormat;
275 aFormatVal >>= sFormat;
276 lang::Locale aLoc;
277 aLocale >>= aLoc;
278 sal_Int32 nKey = xDocNumberFormats->queryKey( sFormat, aLoc, true);
279 if(nKey < 0)
280 {
281 nKey = xDocNumberFormats->addNew( sFormat, aLoc );
282 }
283 pNew->nDBNumFormat = nKey;
284 }
285 catch (const Exception&)
286 {
287 OSL_FAIL("illegal number format key")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "287" ": "), "%s", "illegal number format key"); } } while
(false)
;
288 }
289 }
290 }
291 else
292 {
293 pNew->nDBNumFormat = getDefaultNumberFormat(xCol,
294 xDocNumberFormatTypes, LanguageTag( rSh.GetCurLang() ).getLocale());
295 }
296
297 }
298 break;
299 }
300 if( !aDBColumns.insert( std::move(pNew) ).second )
301 {
302 OSL_ENSURE( false, "Spaltenname mehrfach vergeben?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "302" ": "), "%s", "Spaltenname mehrfach vergeben?"); } }
while (false)
;
303 }
304 }
305 }
306
307 // fill paragraph templates-ListBox
308 {
309 SfxStyleSheetBasePool* pPool = pView->GetDocShell()->GetStyleSheetPool();
310 m_xLbDbParaColl->append_text( sNoTmpl );
311
312 const SfxStyleSheetBase* pBase = pPool->First(SfxStyleFamily::Para);
313 while( pBase )
314 {
315 m_xLbDbParaColl->append_text( pBase->GetName() );
316 pBase = pPool->Next();
317 }
318 m_xLbDbParaColl->set_active( 0 );
319 }
320
321 // when the cursor is inside of a table, table must NEVER be selectable
322 if( pView->GetWrtShell().GetTableFormat() )
323 {
324 m_xRbAsTable->set_sensitive( false );
325 m_xRbAsField->set_active(true);
326 m_xRbDbFormatFromDb->set_active(true);
327 }
328 else
329 {
330 m_xRbAsTable->set_active(true);
331 m_xRbDbFormatFromDb->set_active(true);
332 m_xIbDbcolOneFrom->set_sensitive( false );
333 m_xIbDbcolAllFrom->set_sensitive( false );
334 }
335
336 // by default, select header button
337 m_xRbHeadlColnms->set_active(true);
338 m_xRbHeadlEmpty->set_active(false);
339
340 m_xRbAsTable->connect_clicked( LINK(this, SwInsertDBColAutoPilot, PageHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubPageHdl)
);
341 m_xRbAsField->connect_clicked( LINK(this, SwInsertDBColAutoPilot, PageHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubPageHdl)
);
342 m_xRbAsText->connect_clicked( LINK(this, SwInsertDBColAutoPilot, PageHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubPageHdl)
);
343
344 m_xRbDbFormatFromDb->connect_clicked( LINK(this, SwInsertDBColAutoPilot, DBFormatHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubDBFormatHdl
)
);
345 m_xRbDbFormatFromUsr->connect_clicked( LINK(this, SwInsertDBColAutoPilot, DBFormatHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubDBFormatHdl
)
);
346
347 m_xPbTableFormat->connect_clicked(LINK(this, SwInsertDBColAutoPilot, TableFormatHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableFormatHdl
)
);
348 m_xPbTableAutofmt->connect_clicked(LINK(this, SwInsertDBColAutoPilot, AutoFormatHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubAutoFormatHdl
)
);
349
350 m_xIbDbcolAllTo->connect_clicked( LINK(this, SwInsertDBColAutoPilot, TableToFromHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableToFromHdl
)
);
351 m_xIbDbcolOneTo->connect_clicked( LINK(this, SwInsertDBColAutoPilot, TableToFromHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableToFromHdl
)
);
352 m_xIbDbcolOneFrom->connect_clicked( LINK(this, SwInsertDBColAutoPilot, TableToFromHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableToFromHdl
)
);
353 m_xIbDbcolAllFrom->connect_clicked( LINK(this, SwInsertDBColAutoPilot, TableToFromHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableToFromHdl
)
);
354 m_xIbDbcolToEdit->connect_clicked( LINK(this, SwInsertDBColAutoPilot, TableToFromHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTableToFromHdl
)
);
355
356 m_xCbTableHeadon->connect_clicked( LINK(this, SwInsertDBColAutoPilot, HeaderHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubHeaderHdl)
);
357 m_xRbHeadlColnms->connect_clicked( LINK(this, SwInsertDBColAutoPilot, HeaderHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubHeaderHdl)
);
358 m_xRbHeadlEmpty->connect_clicked( LINK(this, SwInsertDBColAutoPilot, HeaderHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubHeaderHdl)
);
359
360 m_xLbTextDbColumn->connect_changed( LINK( this, SwInsertDBColAutoPilot, TVSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTVSelectHdl
)
);
361 m_xLbTableDbColumn->connect_changed( LINK( this, SwInsertDBColAutoPilot, TVSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTVSelectHdl
)
);
362 m_xLbDbFormatFromUsr->connect_changed( LINK( this, SwInsertDBColAutoPilot, CBSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubCBSelectHdl
)
);
363 m_xLbTableCol->connect_changed( LINK( this, SwInsertDBColAutoPilot, TVSelectHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubTVSelectHdl
)
);
364
365 m_xLbTextDbColumn->connect_row_activated( LINK( this, SwInsertDBColAutoPilot, DblClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubDblClickHdl
)
);
366 m_xLbTableDbColumn->connect_row_activated( LINK( this, SwInsertDBColAutoPilot, DblClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubDblClickHdl
)
);
367 m_xLbTableCol->connect_row_activated( LINK( this, SwInsertDBColAutoPilot, DblClickHdl )::tools::detail::makeLink( ::tools::detail::castTo<SwInsertDBColAutoPilot
*>(this), &SwInsertDBColAutoPilot::LinkStubDblClickHdl
)
);
368
369 for( size_t n = 0; n < aDBColumns.size(); ++n )
370 {
371 const OUString& rS = aDBColumns[ n ]->sColumn;
372 m_xLbTableDbColumn->append_text(rS);
373 m_xLbTextDbColumn->append_text(rS);
374 }
375 m_xLbTextDbColumn->select(0);
376 m_xLbTableDbColumn->select(0);
377
378 // read configuration
379 Load();
380
381 // lock size to widest config
382 m_xHeadFrame->set_size_request(m_xHeadFrame->get_preferred_size().Width(), -1);
383 // initialise Controls:
384 PageHdl(m_xRbAsTable->get_active() ? *m_xRbAsTable : *m_xRbAsField);
385}
386
387SwInsertDBColAutoPilot::~SwInsertDBColAutoPilot()
388{
389}
390
391IMPL_LINK( SwInsertDBColAutoPilot, PageHdl, weld::Button&, rButton, void )void SwInsertDBColAutoPilot::LinkStubPageHdl(void * instance,
weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->PageHdl(data); } void SwInsertDBColAutoPilot
::PageHdl(weld::Button& rButton)
392{
393 bool bShowTable = &rButton == m_xRbAsTable.get();
394
395 m_xHeadFrame->set_label(MnemonicGenerator::EraseAllMnemonicChars(rButton.get_label().replace('_', '~')));
396
397 m_xLbTextDbColumn->set_visible( !bShowTable );
398 m_xIbDbcolToEdit->set_visible( !bShowTable );
399 m_xEdDbText->set_visible( !bShowTable );
400 m_xFtDbParaColl->set_visible( !bShowTable );
401 m_xLbDbParaColl->set_visible( !bShowTable );
402
403 m_xLbTableDbColumn->set_visible( bShowTable );
404 m_xIbDbcolAllTo->set_visible( bShowTable );
405 m_xIbDbcolOneTo->set_visible( bShowTable );
406 m_xIbDbcolOneFrom->set_visible( bShowTable );
407 m_xIbDbcolAllFrom->set_visible( bShowTable );
408 m_xFtTableCol->set_visible( bShowTable );
409 m_xLbTableCol->set_visible( bShowTable );
410 m_xCbTableHeadon->set_visible( bShowTable );
411 m_xRbHeadlColnms->set_visible( bShowTable );
412 m_xRbHeadlEmpty->set_visible( bShowTable );
413 m_xPbTableFormat->set_visible( bShowTable );
414 m_xPbTableAutofmt->set_visible( bShowTable );
415
416 if( bShowTable )
417 m_xPbTableFormat->set_sensitive( 0 != m_xLbTableCol->n_children() );
418
419 TVSelectHdl( bShowTable ? *m_xLbTableDbColumn : *m_xLbTextDbColumn );
420}
421
422IMPL_LINK( SwInsertDBColAutoPilot, DBFormatHdl, weld::Button&, rButton, void )void SwInsertDBColAutoPilot::LinkStubDBFormatHdl(void * instance
, weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->DBFormatHdl(data); } void SwInsertDBColAutoPilot
::DBFormatHdl(weld::Button& rButton)
423{
424 weld::TreeView& rBox = m_xRbAsTable->get_active()
425 ? ( m_xLbTableCol->get_id(0).isEmpty()
426 ? *m_xLbTableDbColumn
427 : *m_xLbTableCol )
428 : *m_xLbTextDbColumn;
429
430 SwInsDBColumn aSrch(rBox.get_selected_text());
431 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
432
433 bool bFromDB = m_xRbDbFormatFromDb.get() == &rButton;
434 (*it)->bIsDBFormat = bFromDB;
435 m_xLbDbFormatFromUsr->set_sensitive( !bFromDB );
436}
437
438IMPL_LINK( SwInsertDBColAutoPilot, TableToFromHdl, weld::Button&, rButton, void )void SwInsertDBColAutoPilot::LinkStubTableToFromHdl(void * instance
, weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->TableToFromHdl(data); } void SwInsertDBColAutoPilot
::TableToFromHdl(weld::Button& rButton)
439{
440 bool bChgEnable = true, bEnableTo = true, bEnableFrom = true;
441
442 if( &rButton == m_xIbDbcolAllTo.get() )
443 {
444 bEnableTo = false;
445
446 sal_Int32 n, nInsPos = m_xLbTableCol->get_selected_index(),
447 nCnt = m_xLbTableDbColumn->n_children();
448
449 m_xLbTableDbColumn->unselect_all();
450
451 m_xLbTableDbColumn->freeze();
452 m_xLbTableCol->freeze();
453
454 if (nInsPos == -1)
455 for( n = 0; n < nCnt; ++n )
456 m_xLbTableCol->append_text(m_xLbTableDbColumn->get_text(n));
457 else
458 for( n = 0; n < nCnt; ++n, ++nInsPos )
459 m_xLbTableCol->insert_text(nInsPos, m_xLbTableDbColumn->get_text(n));
460 m_xLbTableDbColumn->clear();
461
462 m_xLbTableDbColumn->thaw();
463 m_xLbTableCol->thaw();
464
465 m_xLbTableCol->select(nInsPos);
466 }
467 else if( &rButton == m_xIbDbcolOneTo.get() &&
468 m_xLbTableDbColumn->get_selected_index() != -1 )
469 {
470 sal_Int32 nInsPos = m_xLbTableCol->get_selected_index(),
471 nDelPos = m_xLbTableDbColumn->get_selected_index();
472 m_xLbTableCol->insert_text(nInsPos, m_xLbTableDbColumn->get_text(nDelPos));
473 m_xLbTableDbColumn->remove(nDelPos);
474
475 m_xLbTableCol->select(nInsPos);
476 if (nDelPos >= m_xLbTableDbColumn->n_children())
477 nDelPos = m_xLbTableDbColumn->n_children() - 1;
478 m_xLbTableDbColumn->select(nDelPos);
479
480 bEnableTo = 0 != m_xLbTableDbColumn->n_children();
481 }
482 else if( &rButton == m_xIbDbcolOneFrom.get() )
483 {
484 if (m_xLbTableCol->get_selected_index() != -1)
485 {
486 sal_Int32 nInsPos,
487 nDelPos = m_xLbTableCol->get_selected_index();
488
489 // look for the right InsertPos!!
490 SwInsDBColumn aSrch(m_xLbTableCol->get_text(nDelPos));
491 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
492 if( it == aDBColumns.begin() || (it+1) == aDBColumns.end() )
493 nInsPos = it - aDBColumns.begin();
494 else
495 {
496 nInsPos = -1;
497 while( ++it != aDBColumns.end() &&
498 -1 == (nInsPos = m_xLbTableDbColumn->
499 find_text( (*it)->sColumn )) )
500 ;
501 }
502
503 m_xLbTableDbColumn->insert_text(nInsPos, aSrch.sColumn);
504 m_xLbTableCol->remove( nDelPos );
505
506 if (nInsPos >= m_xLbTableDbColumn->n_children())
507 nInsPos = m_xLbTableDbColumn->n_children() - 1;
508 m_xLbTableDbColumn->select(nInsPos);
509
510 if (nDelPos >= m_xLbTableCol->n_children())
511 nDelPos = m_xLbTableCol->n_children() - 1;
512 m_xLbTableCol->select(nDelPos);
513 }
514 else
515 bEnableTo = 0 != m_xLbTableDbColumn->n_children();
516
517 bEnableFrom = 0 != m_xLbTableCol->n_children();
518 }
519 else if( &rButton == m_xIbDbcolAllFrom.get() )
520 {
521 bEnableFrom = false;
522
523 m_xLbTableDbColumn->freeze();
524 m_xLbTableCol->freeze();
525
526 m_xLbTableDbColumn->clear();
527 m_xLbTableCol->clear();
528 for (size_t n = 0; n < aDBColumns.size(); ++n)
529 m_xLbTableDbColumn->append_text(aDBColumns[n]->sColumn);
530
531 m_xLbTableDbColumn->thaw();
532 m_xLbTableCol->thaw();
533
534 m_xLbTableDbColumn->select(0);
535 }
536 else if( &rButton == m_xIbDbcolToEdit.get() )
537 {
538 bChgEnable = false;
539 // move data to Edit:
540 OUString aField(m_xLbTextDbColumn->get_selected_text());
541 if( !aField.isEmpty() )
542 {
543 OUString aStr( m_xEdDbText->get_text() );
544 int nStartPos, nEndPos;
545 m_xEdDbText->get_selection_bounds(nStartPos, nEndPos);
546 sal_Int32 nPos = std::min(nStartPos, nEndPos);
547 sal_Int32 nMax = std::max(nStartPos, nEndPos);
548 const sal_Int32 nSel = nMax - nPos;
549 if( nSel )
550 // first delete the existing selection
551 aStr = aStr.replaceAt( nPos, nSel, "" );
552
553 aField = OUStringChar(cDBFieldStart) + aField + OUStringChar(cDBFieldEnd);
554 if( !aStr.isEmpty() )
555 {
556 if( nPos ) // one blank in front
557 {
558 sal_Unicode c = aStr[ nPos-1 ];
559 if( '\n' != c && '\r' != c )
560 aField = " " + aField;
561 }
562 if( nPos < aStr.getLength() ) // one blank behind
563 {
564 sal_Unicode c = aStr[ nPos ];
565 if( '\n' != c && '\r' != c )
566 aField += " ";
567 }
568 }
569
570 m_xEdDbText->set_text( aStr.replaceAt( nPos, 0, aField ) );
571 nPos += aField.getLength();
572 m_xEdDbText->select_region(nPos, nPos);
573 }
574 }
575
576 if( !bChgEnable )
577 return;
578
579 m_xIbDbcolOneTo->set_sensitive( bEnableTo );
580 m_xIbDbcolAllTo->set_sensitive( bEnableTo );
581 m_xIbDbcolOneFrom->set_sensitive( bEnableFrom );
582 m_xIbDbcolAllFrom->set_sensitive( bEnableFrom );
583
584 m_xRbDbFormatFromDb->set_sensitive( false );
585 m_xRbDbFormatFromUsr->set_sensitive( false );
586 m_xLbDbFormatFromUsr->set_sensitive( false );
587
588 m_xPbTableFormat->set_sensitive( bEnableFrom );
589}
590
591IMPL_LINK(SwInsertDBColAutoPilot, DblClickHdl, weld::TreeView&, rBox, bool)bool SwInsertDBColAutoPilot::LinkStubDblClickHdl(void * instance
, weld::TreeView& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->DblClickHdl(data); } bool SwInsertDBColAutoPilot
::DblClickHdl(weld::TreeView& rBox)
592{
593 weld::Button* pButton = nullptr;
594 if( &rBox == m_xLbTextDbColumn.get() )
595 pButton = m_xIbDbcolToEdit.get();
596 else if( &rBox == m_xLbTableDbColumn.get() && m_xIbDbcolOneTo->get_sensitive() )
597 pButton = m_xIbDbcolOneTo.get();
598 else if( &rBox == m_xLbTableCol.get() && m_xIbDbcolOneFrom->get_sensitive() )
599 pButton = m_xIbDbcolOneFrom.get();
600
601 if (pButton)
602 TableToFromHdl(*pButton);
603
604 return true;
605}
606
607IMPL_LINK_NOARG(SwInsertDBColAutoPilot, TableFormatHdl, weld::Button&, void)void SwInsertDBColAutoPilot::LinkStubTableFormatHdl(void * instance
, weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->TableFormatHdl(data); } void SwInsertDBColAutoPilot
::TableFormatHdl(__attribute__ ((unused)) weld::Button&)
608{
609 SwWrtShell& rSh = pView->GetWrtShell();
610 bool bNewSet = false;
611 if( !pTableSet )
612 {
613 bNewSet = true;
614 pTableSet.reset(new SfxItemSet( rSh.GetAttrPool(), SwuiGetUITableAttrRange() ));
615
616 // At first acquire the simple attributes
617 pTableSet->Put( SfxStringItem( FN_PARAM_TABLE_NAME((20000 + 1100)+44), rSh.GetUniqueTableName() ));
618 pTableSet->Put( SfxUInt16Item( FN_PARAM_TABLE_HEADLINE((20000 + 1100)+50), 1 ) );
619
620 pTableSet->Put( SfxUInt16Item( SID_BACKGRND_DESTINATION( 10000 + 404 ),
621 rSh.GetViewOptions()->GetTableDest() ));
622
623 SvxBrushItem aBrush( RES_BACKGROUND );
624 pTableSet->Put( aBrush );
625 aBrush.SetWhich(SID_ATTR_BRUSH_ROW( 10000 + 368 ));
626 pTableSet->Put( aBrush );
627 aBrush.SetWhich(SID_ATTR_BRUSH_TABLE( 10000 + 453 ));
628 pTableSet->Put( aBrush );
629
630 SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNERTypedWhichId<SvxBoxInfoItem>( 10000 + 23 ) );
631 // table variant, when multiple table cells are selected
632 aBoxInfo.SetTable( true );
633 // always show gap field
634 aBoxInfo.SetDist( true);
635 // set minimum size in tables and paragraphs
636 aBoxInfo.SetMinDist( false );
637 // always set default-gap
638 aBoxInfo.SetDefDist( MIN_BORDER_DIST28 );
639 // Single lines can have DontCare-status only in tables
640 aBoxInfo.SetValid( SvxBoxInfoItemValidFlags::DISABLE );
641 pTableSet->Put( aBoxInfo );
642
643 SwGetCurColNumPara aPara;
644 const sal_uInt16 nNum = rSh.GetCurColNum( &aPara );
645 long nWidth;
646
647 if( nNum )
648 {
649 nWidth = aPara.pPrtRect->Width();
650 const SwFormatCol& rCol = aPara.pFrameFormat->GetCol();
651 const SwColumns& rCols = rCol.GetColumns();
652
653 // initialise nStart and nEnd for nNum == 0
654 long nWidth1 = 0,
655 nStart1 = 0,
656 nEnd1 = nWidth;
657 for( sal_uInt16 i = 0; i < nNum; ++i )
658 {
659 const SwColumn* pCol = &rCols[i];
660 nStart1 = pCol->GetLeft() + nWidth1;
661 nWidth1 += static_cast<long>(rCol.CalcColWidth( i, static_cast<sal_uInt16>(nWidth) ));
662 nEnd1 = nWidth1 - pCol->GetRight();
663 }
664 if(nStart1 || nEnd1 != nWidth)
665 nWidth = nEnd1 - nStart1;
666 }
667 else
668 nWidth = rSh.GetAnyCurRect(
669 (FrameTypeFlags::FLY_ANY & rSh.GetFrameType( nullptr, true ))
670 ? CurRectType::FlyEmbeddedPrt
671 : CurRectType::PagePrt ).Width();
672
673 SwTabCols aTabCols;
674 aTabCols.SetRight( nWidth );
675 aTabCols.SetRightMax( nWidth );
676 pRep.reset(new SwTableRep( aTabCols ));
677 pRep->SetAlign( text::HoriOrientation::NONE );
678 pRep->SetSpace( nWidth );
679 pRep->SetWidth( nWidth );
680 pRep->SetWidthPercent( 100 );
681 pTableSet->Put( SwPtrItem( FN_TABLE_REP((20000 + 400) + 99), pRep.get() ));
682
683 pTableSet->Put( SfxUInt16Item( SID_HTML_MODE(10000 + 414),
684 ::GetHtmlMode( pView->GetDocShell() )));
685 }
686
687 sal_Int32 nCols = m_xLbTableCol->n_children();
688 if (nCols != pRep->GetAllColCount() && nCols > 0)
689 {
690 // Number of columns has changed: then the TabCols have to be adjusted
691 long nWidth = pRep->GetWidth();
692 --nCols;
693 SwTabCols aTabCols( nCols );
694 aTabCols.SetRight( nWidth );
695 aTabCols.SetRightMax( nWidth );
696 if( nCols )
697 {
698 const sal_Int32 nStep = nWidth / (nCols+1);
699 for( sal_Int32 n = 0; n < nCols; ++n )
700 {
701 aTabCols.Insert( nStep*(n+1), false, n );
702 }
703 }
704 pRep.reset(new SwTableRep( aTabCols ));
705 pRep->SetAlign( text::HoriOrientation::NONE );
706 pRep->SetSpace( nWidth );
707 pRep->SetWidth( nWidth );
708 pRep->SetWidthPercent( 100 );
709 pTableSet->Put( SwPtrItem( FN_TABLE_REP((20000 + 400) + 99), pRep.get() ));
710 }
711
712 SwAbstractDialogFactory& rFact = swui::GetFactory();
713
714 ScopedVclPtr<SfxAbstractTabDialog> pDlg(rFact.CreateSwTableTabDlg(m_xDialog.get(), pTableSet.get(), &rSh));
715 if( RET_OK == pDlg->Execute() )
716 pTableSet->Put( *pDlg->GetOutputItemSet() );
717 else if( bNewSet )
718 {
719 pTableSet.reset();
720 pRep.reset();
721 }
722}
723
724IMPL_LINK_NOARG(SwInsertDBColAutoPilot, AutoFormatHdl, weld::Button&, void)void SwInsertDBColAutoPilot::LinkStubAutoFormatHdl(void * instance
, weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->AutoFormatHdl(data); } void SwInsertDBColAutoPilot
::AutoFormatHdl(__attribute__ ((unused)) weld::Button&)
1
Calling 'SwInsertDBColAutoPilot::AutoFormatHdl'
725{
726 SwAbstractDialogFactory& rFact = swui::GetFactory();
727
728 ScopedVclPtr<AbstractSwAutoFormatDlg> pDlg(rFact.CreateSwAutoFormatDlg(m_xDialog.get(), pView->GetWrtShellPtr(), false, m_xTAutoFormat.get()));
2
Calling constructor for 'ScopedVclPtr<AbstractSwAutoFormatDlg>'
9
Returning from constructor for 'ScopedVclPtr<AbstractSwAutoFormatDlg>'
10
Calling implicit destructor for 'VclPtr<AbstractSwAutoFormatDlg>'
11
Calling '~Reference'
18
Returning from '~Reference'
19
Returning from destructor for 'VclPtr<AbstractSwAutoFormatDlg>'
729 if( RET_OK == pDlg->Execute())
20
Calling 'VclPtr::operator->'
730 m_xTAutoFormat = pDlg->FillAutoFormatOfIndex();
731}
732
733IMPL_LINK(SwInsertDBColAutoPilot, TVSelectHdl, weld::TreeView&, rBox, void)void SwInsertDBColAutoPilot::LinkStubTVSelectHdl(void * instance
, weld::TreeView& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->TVSelectHdl(data); } void SwInsertDBColAutoPilot
::TVSelectHdl(weld::TreeView& rBox)
734{
735 weld::TreeView* pGetBox = &rBox;
736
737 SwInsDBColumn aSrch(pGetBox->get_selected_text());
738 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
739
740 // set the selected FieldName at the FormatGroupBox, so that
741 // it's clear what field is configured by the format!
742 OUString sText( m_xFormatFrame->get_label().copy( 0, nGBFormatLen ));
743 if( aSrch.sColumn.isEmpty() )
744 {
745 m_xRbDbFormatFromDb->set_sensitive( false );
746 m_xRbDbFormatFromUsr->set_sensitive( false );
747 m_xLbDbFormatFromUsr->set_sensitive( false );
748 }
749 else
750 {
751 bool bEnableFormat = (*it)->bHasFormat;
752 m_xRbDbFormatFromDb->set_sensitive( bEnableFormat );
753 m_xRbDbFormatFromUsr->set_sensitive( bEnableFormat );
754
755 if( bEnableFormat )
756 {
757 sText += " (" + aSrch.sColumn + ")";
758 }
759
760 bool bIsDBFormat = (*it)->bIsDBFormat;
761 m_xRbDbFormatFromDb->set_active( bIsDBFormat );
762 m_xRbDbFormatFromUsr->set_active( !bIsDBFormat );
763 m_xLbDbFormatFromUsr->set_sensitive( !bIsDBFormat );
764 if( !bIsDBFormat )
765 m_xLbDbFormatFromUsr->SetDefFormat( (*it)->nUsrNumFormat );
766 }
767
768 m_xFormatFrame->set_label(sText);
769
770 if (m_xLbTableCol->n_children())
771 {
772 // to know later on, what ListBox was the "active", a Flag
773 // is remembered in the 1st entry
774 if (&rBox == m_xLbTableCol.get())
775 m_xLbTableCol->set_id(0, "tablecols");
776 else
777 m_xLbTableCol->set_id(0, OUString());
778 }
779}
780
781IMPL_LINK_NOARG(SwInsertDBColAutoPilot, CBSelectHdl, weld::ComboBox&, void)void SwInsertDBColAutoPilot::LinkStubCBSelectHdl(void * instance
, weld::ComboBox& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->CBSelectHdl(data); } void SwInsertDBColAutoPilot
::CBSelectHdl(__attribute__ ((unused)) weld::ComboBox&)
782{
783 weld::TreeView* pGetBox = m_xRbAsTable->get_active()
784 ? ( m_xLbTableCol->get_id(0).isEmpty()
785 ? m_xLbTableDbColumn.get()
786 : m_xLbTableCol.get() )
787 : m_xLbTextDbColumn.get();
788
789 SwInsDBColumn aSrch(pGetBox->get_selected_text());
790 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
791
792 if( !aSrch.sColumn.isEmpty() )
793 {
794 m_xLbDbFormatFromUsr->CallSelectHdl();
795 (*it)->nUsrNumFormat = m_xLbDbFormatFromUsr->GetFormat();
796 }
797}
798
799IMPL_LINK( SwInsertDBColAutoPilot, HeaderHdl, weld::Button&, rButton, void )void SwInsertDBColAutoPilot::LinkStubHeaderHdl(void * instance
, weld::Button& data) { return static_cast<SwInsertDBColAutoPilot
*>(instance)->HeaderHdl(data); } void SwInsertDBColAutoPilot
::HeaderHdl(weld::Button& rButton)
800{
801 if (&rButton == m_xCbTableHeadon.get())
802 {
803 bool bEnable = m_xCbTableHeadon->get_active();
804
805 m_xRbHeadlColnms->set_sensitive( bEnable );
806 m_xRbHeadlEmpty->set_sensitive( bEnable );
807 }
808}
809
810static void lcl_InsTextInArr( const OUString& rText, DB_Columns& rColArr )
811{
812 sal_Int32 nSttPos = 0, nFndPos;
813 while( -1 != ( nFndPos = rText.indexOf( '\x0A', nSttPos )) )
814 {
815 if( 1 < nFndPos )
816 {
817 rColArr.push_back(std::make_unique<DB_Column>(rText.copy(nSttPos, nFndPos -1)));
818 }
819 rColArr.push_back(std::make_unique<DB_Column>());
820 nSttPos = nFndPos + 1;
821 }
822 if( nSttPos < rText.getLength() )
823 {
824 rColArr.push_back(std::make_unique<DB_Column>(rText.copy(nSttPos)));
825 }
826}
827
828bool SwInsertDBColAutoPilot::SplitTextToColArr( const OUString& rText,
829 DB_Columns& rColArr,
830 bool bInsField )
831{
832 // create each of the database columns from the text again
833 // and then save in an array
834 // database columns are in <> and must be present in the columns' array:
835 OUString sText( rText );
836 sal_Int32 nFndPos, nEndPos, nSttPos = 0;
837
838 while( -1 != ( nFndPos = sText.indexOf( cDBFieldStart, nSttPos )))
839 {
840 nSttPos = nFndPos + 1;
841 nEndPos = sText.indexOf( cDBFieldEnd, nSttPos+1 );
842 if( -1 != nEndPos )
843 {
844 // Text in <> brackets found: what is it:
845 SwInsDBColumn aSrch( sText.copy( nSttPos, nEndPos - nSttPos ));
846 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
847 if( it != aDBColumns.end() )
848 {
849 // that is a valid field
850 // so surely the text "before":
851 const SwInsDBColumn& rFndCol = **it;
852
853 DB_Column* pNew;
854
855 if( 1 < nSttPos )
856 {
857 ::lcl_InsTextInArr( sText.copy( 0, nSttPos-1 ), rColArr );
858 sText = sText.copy( nSttPos-1 );
859 }
860
861 sText = sText.copy( rFndCol.sColumn.getLength() + 2 );
862 nSttPos = 0;
863
864 sal_uInt16 nSubType = 0;
865 sal_uInt32 nFormat;
866 if( rFndCol.bHasFormat )
867 {
868 if( rFndCol.bIsDBFormat )
869 nFormat = static_cast<sal_uInt32>(rFndCol.nDBNumFormat);
870 else
871 {
872 nFormat = rFndCol.nUsrNumFormat;
873 nSubType = nsSwExtendedSubType::SUB_OWN_FMT;
874 }
875 }
876 else
877 nFormat = 0;
878
879 if( bInsField )
880 {
881 SwWrtShell& rSh = pView->GetWrtShell();
882 SwDBFieldType aFieldType( rSh.GetDoc(), aSrch.sColumn,
883 aDBData );
884 pNew = new DB_Column( rFndCol, *new SwDBField(
885 static_cast<SwDBFieldType*>(rSh.InsertFieldType( aFieldType )),
886 nFormat ) );
887 if( nSubType )
888 pNew->pField->SetSubType( nSubType );
889 }
890 else
891 pNew = new DB_Column( rFndCol, nFormat );
892
893 rColArr.push_back( std::unique_ptr<DB_Column>(pNew) );
894 }
895 }
896 }
897
898 // don't forget the last text
899 if( !sText.isEmpty() )
900 ::lcl_InsTextInArr( sText, rColArr );
901
902 return !rColArr.empty();
903}
904
905void SwInsertDBColAutoPilot::DataToDoc( const Sequence<Any>& rSelection,
906 Reference< XDataSource> const & xSource,
907 Reference< XConnection> const & xConnection,
908 Reference< sdbc::XResultSet > const & xResultSet_in )
909{
910 auto xResultSet = xResultSet_in;
911
912 const Any* pSelection = rSelection.hasElements() ? rSelection.getConstArray() : nullptr;
913 SwWrtShell& rSh = pView->GetWrtShell();
914
915 //with the drag and drop interface no result set is initially available
916 bool bDisposeResultSet = false;
917 // we don't have a cursor, so we have to create our own RowSet
918 if ( !xResultSet.is() )
919 {
920 xResultSet = SwDBManager::createCursor(aDBData.sDataSource,aDBData.sCommand,aDBData.nCommandType,xConnection,pView);
921 bDisposeResultSet = xResultSet.is();
922 }
923
924 Reference< sdbc::XRow > xRow(xResultSet, UNO_QUERY);
925 if ( !xRow.is() )
926 return;
927
928 rSh.StartAllAction();
929 bool bUndo = rSh.DoesUndo();
930 if( bUndo )
931 rSh.StartUndo();
932
933 bool bAsTable = m_xRbAsTable->get_active();
934 SvNumberFormatter& rNumFormatr = *rSh.GetNumberFormatter();
935
936 if( rSh.HasSelection() )
937 rSh.DelRight();
938
939 std::unique_ptr<SwWait> pWait;
940
941 Reference< XColumnsSupplier > xColsSupp( xResultSet, UNO_QUERY );
942 Reference <XNameAccess> xCols = xColsSupp->getColumns();
943
944 uno::Reference<sdbcx::XRowLocate> xRowLocate(xResultSet, uno::UNO_QUERY_THROW);
945
946 do{ // middle checked loop!!
947 if( bAsTable ) // fill in data as table
948 {
949 rSh.DoUndo( false );
950
951 sal_Int32 nCols = m_xLbTableCol->n_children();
952 sal_Int32 nRows = 0;
953 if( m_xCbTableHeadon->get_active() )
954 nRows++;
955
956 if( pSelection )
957 nRows += rSelection.getLength();
958 else
959 ++nRows;
960
961 // prepare the array for the selected columns
962 std::vector<SwInsDBColumn*> aColFields;
963 for( sal_Int32 n = 0; n < nCols; ++n )
964 {
965 SwInsDBColumn aSrch(m_xLbTableCol->get_text(n));
966 SwInsDBColumns::const_iterator it = aDBColumns.find( &aSrch );
967 if (it != aDBColumns.end())
968 aColFields.push_back(it->get());
969 else {
970 OSL_ENSURE( false, "database column not found" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "970" ": "), "%s", "database column not found"); } } while
(false)
;
971 }
972 }
973
974 if( static_cast<size_t>(nCols) != aColFields.size() )
975 {
976 OSL_ENSURE( false, "not all database columns found" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "976" ": "), "%s", "not all database columns found"); } }
while (false)
;
977 nCols = static_cast<sal_Int32>(aColFields.size());
978 }
979
980 if(!nRows || !nCols)
981 {
982 OSL_ENSURE( false, "wrong parameters" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "982" ": "), "%s", "wrong parameters"); } } while (false
)
;
983 break;
984 }
985
986 const SwModuleOptions* pModOpt = SW_MOD()( static_cast<SwModule*>(SfxApplication::GetModule(SfxToolsModule
::Writer)))
->GetModuleConfig();
987
988 bool bHTML = 0 != (::GetHtmlMode( pView->GetDocShell() ) & HTMLMODE_ON);
989 rSh.InsertTable(
990 pModOpt->GetInsTableFlags(bHTML),
991 nRows, nCols, (pSelection ? m_xTAutoFormat.get(): nullptr) );
992 rSh.MoveTable( GotoPrevTable, fnTableStart );
993
994 if( pSelection && pTableSet )
995 SetTabSet();
996
997 SfxItemSet aTableSet( rSh.GetAttrPool(), svl::Items<RES_BOXATR_FORMAT,
998 RES_BOXATR_VALUE>{} );
999 bool bIsAutoUpdateCells = rSh.IsAutoUpdateCells();
1000 rSh.SetAutoUpdateCells( false );
1001
1002 if( m_xCbTableHeadon->get_active() )
1003 {
1004 for( sal_Int32 n = 0; n < nCols; ++n )
1005 {
1006 if( m_xRbHeadlColnms->get_active() )
1007 {
1008 rSh.SwEditShell::Insert2( aColFields[ n ]->sColumn );
1009 }
1010 rSh.GoNextCell();
1011 }
1012 }
1013 else
1014 rSh.SetRowsToRepeat( 0 );
1015
1016 for( sal_Int32 i = 0 ; ; ++i )
1017 {
1018 bool bBreak = false;
1019 try
1020 {
1021 if(pSelection)
1022 {
1023 bBreak = !xRowLocate->moveToBookmark(pSelection[i]);
1024 }
1025 else if(!i)
1026 bBreak = !xResultSet->first();
1027 }
1028 catch (const Exception&)
1029 {
1030 bBreak = true;
1031 }
1032 if(bBreak)
1033 break;
1034
1035 for( sal_Int32 n = 0; n < nCols; ++n )
1036 {
1037 // at the very first time, NO GoNextCell, because we're
1038 // already in it. Also no GoNextCell after the Insert,
1039 // because an empty line is added at the end.
1040 if( i || n )
1041 rSh.GoNextCell();
1042
1043 const SwInsDBColumn* pEntry = aColFields[ n ];
1044
1045 Reference< XColumn > xColumn;
1046 xCols->getByName(pEntry->sColumn) >>= xColumn;
1047 Reference< XPropertySet > xColumnProps( xColumn, UNO_QUERY );
1048 sal_Int32 eDataType = 0;
1049 if( xColumnProps.is() )
1050 {
1051 Any aType = xColumnProps->getPropertyValue("Type");
1052 aType >>= eDataType;
1053 }
1054 try
1055 {
1056 if( pEntry->bHasFormat )
1057 {
1058 SwTableBoxNumFormat aNumFormat(
1059 pEntry->bIsDBFormat ? static_cast<sal_uInt32>(pEntry->nDBNumFormat)
1060 : pEntry->nUsrNumFormat );
1061 aTableSet.Put(aNumFormat);
1062 if( xColumn.is() )
1063 {
1064 double fVal = xColumn->getDouble();
1065 if( xColumn->wasNull() )
1066 aTableSet.ClearItem( RES_BOXATR_VALUE );
1067 else
1068 {
1069 if(rNumFormatr.GetType(aNumFormat.GetValue()) & SvNumFormatType::DATE)
1070 {
1071 ::Date aStandard(1,1,1900);
1072 if (rNumFormatr.GetNullDate() != aStandard)
1073 fVal += (aStandard - rNumFormatr.GetNullDate());
1074 }
1075 aTableSet.Put( SwTableBoxValue( fVal ));
1076 }
1077 }
1078 else
1079 aTableSet.ClearItem( RES_BOXATR_VALUE );
1080 rSh.SetTableBoxFormulaAttrs( aTableSet );
1081 }
1082 //#i60207# don't insert binary data as string - creates a loop
1083 else if( DataType::BINARY == eDataType ||
1084 DataType::VARBINARY == eDataType ||
1085 DataType::LONGVARBINARY== eDataType ||
1086 DataType::SQLNULL == eDataType ||
1087 DataType::OTHER == eDataType ||
1088 DataType::OBJECT == eDataType ||
1089 DataType::DISTINCT == eDataType ||
1090 DataType::STRUCT == eDataType ||
1091 DataType::ARRAY == eDataType ||
1092 DataType::BLOB == eDataType ||
1093 DataType::CLOB == eDataType ||
1094 DataType::REF == eDataType
1095 )
1096 {
1097 // do nothing
1098 }
1099 else
1100 {
1101 const OUString sVal = xColumn->getString();
1102 if(!xColumn->wasNull())
1103 {
1104 rSh.SwEditShell::Insert2( sVal );
1105 }
1106 }
1107 }
1108 catch (const Exception&)
1109 {
1110 TOOLS_WARN_EXCEPTION("sw", "")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"sw"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "1110" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "1110" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"sw"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "1110" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw"), ("/home/maarten/src/libreoffice/core/sw/source/ui/dbui/dbinsdlg.cxx"
":" "1110" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
1111 }
1112 }
1113
1114 if( !pSelection )
1115 {
1116 if ( !xResultSet->next() )
1117 break;
1118 }
1119 else if( i+1 >= rSelection.getLength() )
1120 break;
1121
1122 if( 10 == i )
1123 pWait.reset(new SwWait( *pView->GetDocShell(), true ));
1124 }
1125
1126 rSh.MoveTable( GotoCurrTable, fnTableStart );
1127 if( !pSelection && ( pTableSet || m_xTAutoFormat ))
1128 {
1129 if( pTableSet )
1130 SetTabSet();
1131
1132 if (m_xTAutoFormat)
1133 rSh.SetTableStyle(*m_xTAutoFormat);
1134 }
1135 rSh.SetAutoUpdateCells( bIsAutoUpdateCells );
1136 }
1137 else // add data as fields/text
1138 {
1139 DB_Columns aColArr;
1140 if( SplitTextToColArr( m_xEdDbText->get_text(), aColArr, m_xRbAsField->get_active() ) )
1141 {
1142 // now for each data set, we can iterate over the array
1143 // and add the data
1144
1145 if( !rSh.IsSttPara() )
1146 rSh.SwEditShell::SplitNode();
1147 if( !rSh.IsEndPara() )
1148 {
1149 rSh.SwEditShell::SplitNode();
1150 rSh.SwCursorShell::Left(1,CRSR_SKIP_CHARS);
1151 }
1152
1153 rSh.DoUndo( false );
1154
1155 SwTextFormatColl* pColl = nullptr;
1156 {
1157 const OUString sTmplNm(m_xLbDbParaColl->get_active_text());
1158 if( sNoTmpl != sTmplNm )
1159 {
1160 pColl = rSh.FindTextFormatCollByName( sTmplNm );
1161 if( !pColl )
1162 {
1163 const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(
1164 sTmplNm, SwGetPoolIdFromName::TxtColl );
1165 if( USHRT_MAX(32767 *2 +1) != nId )
1166 pColl = rSh.GetTextCollFromPool( nId );
1167 else
1168 pColl = rSh.MakeTextFormatColl( sTmplNm );
1169 }
1170 rSh.SetTextFormatColl( pColl );
1171 }
1172 }
1173
1174 // for adding as fields -> insert a "NextField" after
1175 // every data set
1176 SwDBFormatData aDBFormatData;
1177 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1178 aDBFormatData.xFormatter.set(util::NumberFormatter::create(xContext), UNO_QUERY_THROW) ;
1179
1180 Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
1181 if(xSourceProps.is())
1182 {
1183 Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
1184 if(aFormats.hasValue())
1185 {
1186 Reference< util::XNumberFormatsSupplier> xSuppl;
1187 aFormats >>= xSuppl;
1188 if(xSuppl.is())
1189 {
1190 Reference< XPropertySet > xSettings = xSuppl->getNumberFormatSettings();
1191 Any aNull = xSettings->getPropertyValue("NullDate");
1192 aNull >>= aDBFormatData.aNullDate;
1193 if(aDBFormatData.xFormatter.is())
1194 aDBFormatData.xFormatter->attachNumberFormatsSupplier(xSuppl);
1195 }
1196 }
1197 }
1198 aDBFormatData.aLocale = LanguageTag( rSh.GetCurLang() ).getLocale();
1199 SwDBNextSetField aNxtDBField( static_cast<SwDBNextSetFieldType*>(rSh.
1200 GetFieldType( 0, SwFieldIds::DbNextSet )),
1201 "1", aDBData );
1202
1203 bool bSetCursor = true;
1204 const size_t nCols = aColArr.size();
1205 ::sw::mark::IMark* pMark = nullptr;
1206 for( sal_Int32 i = 0 ; ; ++i )
1207 {
1208 bool bBreak = false;
1209 try
1210 {
1211 if(pSelection)
1212 {
1213 bBreak = !xRowLocate->moveToBookmark(pSelection[i]);
1214 }
1215 else if(!i)
1216 bBreak = !xResultSet->first();
1217 }
1218 catch (const Exception&)
1219 {
1220 bBreak = true;
1221 }
1222
1223 if(bBreak)
1224 break;
1225
1226 for( size_t n = 0; n < nCols; ++n )
1227 {
1228 DB_Column* pDBCol = aColArr[ n ].get();
1229 OUString sIns;
1230 switch( pDBCol->eColType )
1231 {
1232 case DB_Column::Type::FILLTEXT:
1233 sIns = *pDBCol->pText;
1234 break;
1235
1236 case DB_Column::Type::SPLITPARA:
1237 rSh.SplitNode();
1238 // when the template is not the same as the follow template,
1239 // the selected has to be set newly
1240 if( pColl && &pColl->GetNextTextFormatColl() != pColl )
1241 rSh.SetTextFormatColl( pColl );
1242 break;
1243
1244 case DB_Column::Type::COL_FIELD:
1245 {
1246 std::unique_ptr<SwDBField> pField(static_cast<SwDBField *>(
1247 pDBCol->pField->CopyField().release()));
1248 double nValue = DBL_MAX1.7976931348623157e+308;
1249
1250 Reference< XPropertySet > xColumnProps;
1251 xCols->getByName(pDBCol->pColInfo->sColumn) >>= xColumnProps;
1252
1253 pField->SetExpansion( SwDBManager::GetDBField(
1254 xColumnProps,
1255 aDBFormatData,
1256 &nValue ) );
1257 if( DBL_MAX1.7976931348623157e+308 != nValue )
1258 {
1259 Any aType = xColumnProps->getPropertyValue("Type");
1260 sal_Int32 eDataType = 0;
1261 aType >>= eDataType;
1262 if( DataType::DATE == eDataType || DataType::TIME == eDataType ||
1263 DataType::TIMESTAMP == eDataType)
1264
1265 {
1266 ::Date aStandard(1,1,1900);
1267 ::Date aCompare(aDBFormatData.aNullDate.Day ,
1268 aDBFormatData.aNullDate.Month,
1269 aDBFormatData.aNullDate.Year);
1270 if(aStandard != aCompare)
1271 nValue += (aStandard - aCompare);
1272 }
1273 pField->ChgValue( nValue, true );
1274 }
1275 pField->SetInitialized();
1276
1277 rSh.Insert( *pField );
1278 }
1279 break;
1280
1281 case DB_Column::Type::COL_TEXT:
1282 {
1283 double nValue = DBL_MAX1.7976931348623157e+308;
1284 Reference< XPropertySet > xColumnProps;
1285 xCols->getByName(pDBCol->pColInfo->sColumn) >>= xColumnProps;
1286 sIns = SwDBManager::GetDBField(
1287 xColumnProps,
1288 aDBFormatData,
1289 &nValue );
1290 if( pDBCol->nFormat &&
1291 DBL_MAX1.7976931348623157e+308 != nValue )
1292 {
1293 const Color* pCol;
1294 if(rNumFormatr.GetType(pDBCol->nFormat) & SvNumFormatType::DATE)
1295 {
1296 ::Date aStandard(1,1,1900);
1297 if (rNumFormatr.GetNullDate() != aStandard)
1298 nValue += (aStandard - rNumFormatr.GetNullDate());
1299 }
1300 rNumFormatr.GetOutputString( nValue,
1301 pDBCol->nFormat,
1302 sIns, &pCol );
1303 }
1304 }
1305 break;
1306 }
1307
1308 if( !sIns.isEmpty() )
1309 {
1310 rSh.Insert( sIns );
1311
1312 if( bSetCursor)
1313 {
1314 // to the beginning and set a mark, so that
1315 // the cursor can be set to the initial position
1316 // at the end.
1317
1318 rSh.SwCursorShell::MovePara(
1319 GoCurrPara, fnParaStart );
1320 pMark = rSh.SetBookmark(
1321 vcl::KeyCode(),
1322 OUString(),
1323 IDocumentMarkAccess::MarkType::UNO_BOOKMARK );
1324 rSh.SwCursorShell::MovePara(
1325 GoCurrPara, fnParaEnd );
1326 bSetCursor = false;
1327 }
1328 }
1329 }
1330
1331 if( !pSelection )
1332 {
1333 bool bNext = xResultSet->next();
1334 if(!bNext)
1335 break;
1336 }
1337 else if( i+1 >= rSelection.getLength() )
1338 break;
1339
1340 if( m_xRbAsField->get_active() )
1341 rSh.Insert( aNxtDBField );
1342
1343 if( !rSh.IsSttPara() )
1344 rSh.SwEditShell::SplitNode();
1345
1346 if( 10 == i )
1347 pWait.reset(new SwWait( *pView->GetDocShell(), true ));
1348 }
1349
1350 if( !bSetCursor && pMark != nullptr)
1351 {
1352 rSh.SetMark();
1353 rSh.GotoMark( pMark );
1354 rSh.getIDocumentMarkAccess()->deleteMark( pMark );
1355 break;
1356 }
1357 }
1358 }
1359 // write configuration
1360 Commit();
1361 }while( false ); // middle checked loop
1362
1363 if( bUndo )
1364 {
1365 rSh.DoUndo();
1366 rSh.AppendUndoForInsertFromDB( bAsTable );
1367 rSh.EndUndo();
1368 }
1369 rSh.ClearMark();
1370 rSh.EndAllAction();
1371
1372 if ( bDisposeResultSet )
1373 ::comphelper::disposeComponent(xResultSet);
1374}
1375
1376void SwInsertDBColAutoPilot::SetTabSet()
1377{
1378 SwWrtShell& rSh = pView->GetWrtShell();
1379 const SfxPoolItem* pItem;
1380
1381 if (m_xTAutoFormat)
1382 {
1383 if (m_xTAutoFormat->IsFrame())
1384 {
1385 // border is from AutoFormat
1386 pTableSet->ClearItem( RES_BOX );
1387 pTableSet->ClearItem( SID_ATTR_BORDER_INNERTypedWhichId<SvxBoxInfoItem>( 10000 + 23 ) );
1388 }
1389 if (m_xTAutoFormat->IsBackground())
1390 {
1391 pTableSet->ClearItem( RES_BACKGROUND );
1392 pTableSet->ClearItem( SID_ATTR_BRUSH_ROW( 10000 + 368 ) );
1393 pTableSet->ClearItem( SID_ATTR_BRUSH_TABLE( 10000 + 453 ) );
1394 }
1395 }
1396 else
1397 {
1398 // remove the defaults again, it makes no sense to set them
1399 SvxBrushItem aBrush( RES_BACKGROUND );
1400 static const sal_uInt16 aIds[3] =
1401 { RES_BACKGROUND, SID_ATTR_BRUSH_ROW( 10000 + 368 ), SID_ATTR_BRUSH_TABLE( 10000 + 453 ) };
1402 for(sal_uInt16 i : aIds)
1403 if( SfxItemState::SET == pTableSet->GetItemState( i,
1404 false, &pItem ) && *pItem == aBrush )
1405 pTableSet->ClearItem( i );
1406 }
1407
1408 if( SfxItemState::SET == pTableSet->GetItemState( FN_PARAM_TABLE_NAME((20000 + 1100)+44), false,
1409 &pItem ) && static_cast<const SfxStringItem*>(pItem)->GetValue() ==
1410 rSh.GetTableFormat()->GetName() )
1411 pTableSet->ClearItem( FN_PARAM_TABLE_NAME((20000 + 1100)+44) );
1412
1413 rSh.MoveTable( GotoCurrTable, fnTableStart );
1414 rSh.SetMark();
1415 rSh.MoveTable( GotoCurrTable, fnTableEnd );
1416
1417 ItemSetToTableParam( *pTableSet, rSh );
1418
1419 rSh.ClearMark();
1420 rSh.MoveTable( GotoCurrTable, fnTableStart );
1421}
1422
1423static Sequence<OUString> lcl_createSourceNames(const OUString& rNodeName)
1424{
1425 Sequence<OUString> aSourceNames(11);
1426 OUString* pNames = aSourceNames.getArray();
1427 pNames[0] = rNodeName + "/DataSource";
1428 pNames[1] = rNodeName + "/Command";
1429 pNames[2] = rNodeName + "/CommandType";
1430 pNames[3] = rNodeName + "/ColumnsToText";
1431 pNames[4] = rNodeName + "/ColumnsToTable";
1432 pNames[5] = rNodeName + "/ParaStyle";
1433 pNames[6] = rNodeName + "/TableAutoFormat";
1434 pNames[7] = rNodeName + "/IsTable";
1435 pNames[8] = rNodeName + "/IsField";
1436 pNames[9] = rNodeName + "/IsHeadlineOn";
1437 pNames[10] = rNodeName + "/IsEmptyHeadline";
1438 return aSourceNames;
1439}
1440
1441static Sequence<OUString> lcl_CreateSubNames(const OUString& rSubNodeName)
1442{
1443 Sequence<OUString> aSubSourceNames(6);
1444 OUString* pNames = aSubSourceNames.getArray();
1445 pNames[0] = rSubNodeName + "/ColumnName";
1446 pNames[1] = rSubNodeName + "/ColumnIndex";
1447 pNames[2] = rSubNodeName + "/IsNumberFormat";
1448 pNames[3] = rSubNodeName + "/IsNumberFormatFromDataBase";
1449 pNames[4] = rSubNodeName + "/NumberFormat";
1450 pNames[5] = rSubNodeName + "/NumberFormatLocale";
1451 return aSubSourceNames;
1452}
1453
1454static OUString lcl_CreateUniqueName(const Sequence<OUString>& aNames)
1455{
1456 sal_Int32 nIdx = aNames.getLength();
1457 while(true)
1458 {
1459 const OUString sRet = "_" + OUString::number(nIdx++);
1460 if ( comphelper::findValue(aNames, sRet) == -1 )
1461 return sRet; // No match found, return unique name
1462 }
1463}
1464
1465void SwInsertDBColAutoPilot::Notify( const css::uno::Sequence< OUString >& ) {}
1466
1467void SwInsertDBColAutoPilot::ImplCommit()
1468{
1469 Sequence <OUString> aNames = GetNodeNames(OUString());
1470 //remove entries that contain this data source + table at first
1471 for(OUString const & nodeName : std::as_const(aNames))
1472 {
1473 Sequence<OUString> aSourceNames(2);
1474 OUString* pSourceNames = aSourceNames.getArray();
1475 pSourceNames[0] = nodeName + "/DataSource";
1476 pSourceNames[1] = nodeName + "/Command";
1477 Sequence<Any> aSourceProperties = GetProperties(aSourceNames);
1478 const Any* pSourceProps = aSourceProperties.getArray();
1479 OUString sSource, sCommand;
1480 pSourceProps[0] >>= sSource;
1481 pSourceProps[1] >>= sCommand;
1482 if(sSource==aDBData.sDataSource && sCommand==aDBData.sCommand)
1483 {
1484 Sequence<OUString> aElements { nodeName };
1485 ClearNodeElements(OUString(), aElements);
1486 }
1487 }
1488
1489 aNames = GetNodeNames(OUString());
1490 OUString sNewNode = lcl_CreateUniqueName(aNames);
1491 Sequence<OUString> aNodeNames = lcl_createSourceNames(sNewNode);
1492 Sequence<PropertyValue> aValues(aNodeNames.getLength());
1493 PropertyValue* pValues = aValues.getArray();
1494 const OUString* pNodeNames = aNodeNames.getConstArray();
1495 for(sal_Int32 i = 0; i < aNodeNames.getLength(); i++)
1496 {
1497 pValues[i].Name = "/" + pNodeNames[i];
1498 }
1499
1500 pValues[0].Value <<= aDBData.sDataSource;
1501 pValues[1].Value <<= aDBData.sCommand;
1502 pValues[2].Value <<= aDBData.nCommandType;
1503 pValues[3].Value <<= m_xEdDbText->get_text();
1504
1505 OUString sTmp;
1506 const sal_Int32 nCnt = m_xLbTableCol->n_children();
1507 for( sal_Int32 n = 0; n < nCnt; ++n )
1508 sTmp += m_xLbTableCol->get_text(n) + "\x0a";
1509
1510 if (!sTmp.isEmpty())
1511 pValues[4].Value <<= sTmp;
1512
1513 if( sNoTmpl != (sTmp = m_xLbDbParaColl->get_active_text()) )
1514 pValues[5].Value <<= sTmp;
1515
1516 if (m_xTAutoFormat)
1517 pValues[6].Value <<= m_xTAutoFormat->GetName();
1518
1519 pValues[7].Value <<= m_xRbAsTable->get_active();
1520 pValues[8].Value <<= m_xRbAsField->get_active();
1521 pValues[9].Value <<= m_xCbTableHeadon->get_active();
1522 pValues[10].Value <<= m_xRbHeadlEmpty->get_active();
1523
1524 SetSetProperties(OUString(), aValues);
1525
1526 sNewNode += "/ColumnSet";
1527
1528 LanguageType ePrevLang(0xffff);
1529
1530 SvNumberFormatter& rNFormatr = *pView->GetWrtShell().GetNumberFormatter();
1531 for(size_t nCol = 0; nCol < aDBColumns.size(); nCol++)
1532 {
1533 SwInsDBColumn* pColumn = aDBColumns[nCol].get();
1534 OUString sColumnInsertNode(sNewNode + "/__");
1535 if( nCol < 10 )
1536 sColumnInsertNode += "00";
1537 else if( nCol < 100 )
1538 sColumnInsertNode += "0";
1539 sColumnInsertNode += OUString::number( nCol );
1540
1541 const Sequence <OUString> aSubNodeNames = lcl_CreateSubNames(sColumnInsertNode);
1542 Sequence<PropertyValue> aSubValues(aSubNodeNames.getLength());
1543 PropertyValue* pSubValues = aSubValues.getArray();
1544 sal_Int32 i = 0;
1545
1546 for( const OUString& rSubNodeName : aSubNodeNames)
1547 pSubValues[i++].Name = rSubNodeName;
1548 pSubValues[0].Value <<= pColumn->sColumn;
1549 pSubValues[1].Value <<= i;
1550 pSubValues[2].Value <<= pColumn->bHasFormat;
1551 pSubValues[3].Value <<= pColumn->bIsDBFormat;
1552
1553 SwStyleNameMapper::FillUIName( RES_POOLCOLL_STANDARD, sTmp );
1554 const SvNumberformat* pNF = rNFormatr.GetEntry( pColumn->nUsrNumFormat );
1555 LanguageType eLang;
1556 if( pNF )
1557 {
1558 pSubValues[4].Value <<= pNF->GetFormatstring();
1559 eLang = pNF->GetLanguage();
1560 }
1561 else
1562 {
1563 pSubValues[4].Value <<= sTmp;
1564 eLang = GetAppLanguage();
1565 }
1566
1567 OUString sPrevLang;
1568 if( eLang != ePrevLang )
1569 {
1570 sPrevLang = LanguageTag::convertToBcp47( eLang );
1571 ePrevLang = eLang;
1572 }
1573
1574 pSubValues[5].Value <<= sPrevLang;
1575 SetSetProperties(sNewNode, aSubValues);
1576 }
1577}
1578
1579void SwInsertDBColAutoPilot::Load()
1580{
1581 const Sequence<OUString> aNames = GetNodeNames(OUString());
1582 SvNumberFormatter& rNFormatr = *pView->GetWrtShell().GetNumberFormatter();
1583 for(OUString const & nodeName : aNames)
1584 {
1585 //search for entries with the appropriate data source and table
1586 Sequence<OUString> aSourceNames = lcl_createSourceNames(nodeName);
1587
1588 Sequence< Any> aDataSourceProps = GetProperties(aSourceNames);
1589 const Any* pDataSourceProps = aDataSourceProps.getConstArray();
1590 OUString sSource, sCommand;
1591 sal_Int16 nCommandType;
1592 pDataSourceProps[0] >>= sSource;
1593 pDataSourceProps[1] >>= sCommand;
1594 pDataSourceProps[2] >>= nCommandType;
1595 if(sSource == aDBData.sDataSource && sCommand == aDBData.sCommand)
1596 {
1597 std::unique_ptr<DB_ColumnConfigData> pNewData(new DB_ColumnConfigData);
1598
1599 pDataSourceProps[3] >>= pNewData->sEdit;
1600 pDataSourceProps[4] >>= pNewData->sTableList;
1601 pDataSourceProps[5] >>= pNewData->sTmplNm;
1602 pDataSourceProps[6] >>= pNewData->sTAutoFormatNm;
1603 if(pDataSourceProps[7].hasValue())
1604 pNewData->bIsTable = *o3tl::doAccess<bool>(pDataSourceProps[7]);
1605 if(pDataSourceProps[8].hasValue())
1606 pNewData->bIsField = *o3tl::doAccess<bool>(pDataSourceProps[8]);
1607 if(pDataSourceProps[9].hasValue())
1608 pNewData->bIsHeadlineOn = *o3tl::doAccess<bool>(pDataSourceProps[9]);
1609 if(pDataSourceProps[10].hasValue())
1610 pNewData->bIsEmptyHeadln = *o3tl::doAccess<bool>(pDataSourceProps[10]);
1611
1612 const OUString sSubNodeName(nodeName + "/ColumnSet/");
1613 const Sequence <OUString> aSubNames = GetNodeNames(sSubNodeName);
1614 for(const OUString& rSubName : aSubNames)
1615 {
1616 Sequence <OUString> aSubNodeNames =
1617 lcl_CreateSubNames(sSubNodeName + rSubName);
1618 Sequence< Any> aSubProps = GetProperties(aSubNodeNames);
1619 const Any* pSubProps = aSubProps.getConstArray();
1620
1621 OUString sColumn;
1622 pSubProps[0] >>= sColumn;
1623 // check for existence of the loaded column name
1624 bool bFound = false;
1625 for(size_t nRealColumn = 0; nRealColumn < aDBColumns.size(); ++nRealColumn)
1626 {
1627 if(aDBColumns[nRealColumn]->sColumn == sColumn)
1628 {
1629 bFound = true;
1630 break;
1631 }
1632 }
1633 if(!bFound)
1634 continue;
1635 sal_Int16 nIndex = 0;
1636 pSubProps[1] >>= nIndex;
1637 std::unique_ptr<SwInsDBColumn> pInsDBColumn(new SwInsDBColumn(sColumn));
1638 if(pSubProps[2].hasValue())
1639 pInsDBColumn->bHasFormat = *o3tl::doAccess<bool>(pSubProps[2]);
1640 if(pSubProps[3].hasValue())
1641 pInsDBColumn->bIsDBFormat = *o3tl::doAccess<bool>(pSubProps[3]);
1642
1643 pSubProps[4] >>= pInsDBColumn->sUsrNumFormat;
1644 OUString sNumberFormatLocale;
1645 pSubProps[5] >>= sNumberFormatLocale;
1646
1647 /* XXX Earlier versions wrote a Country-Language string in
1648 * SwInsertDBColAutoPilot::Commit() that here was read as
1649 * Language-Country with 2 characters copied to language,
1650 * 1 character separator and unconditionally 2 characters read
1651 * as country. So for 'DE-de' and locales that have similar
1652 * case-insensitive equal language/country combos that may have
1653 * worked, for all others not. FIXME if you need to read old
1654 * data that you were never able to read before. */
1655 pInsDBColumn->eUsrNumFormatLng = LanguageTag::convertToLanguageType( sNumberFormatLocale );
1656
1657 pInsDBColumn->nUsrNumFormat = rNFormatr.GetEntryKey( pInsDBColumn->sUsrNumFormat,
1658 pInsDBColumn->eUsrNumFormatLng );
1659
1660 pNewData->aDBColumns.insert(std::move(pInsDBColumn));
1661 }
1662 OUString sTmp( pNewData->sTableList );
1663 if( !sTmp.isEmpty() )
1664 {
1665 sal_Int32 n = 0;
1666 do {
1667 const OUString sEntry( sTmp.getToken( 0, '\x0a', n ) );
1668 //preselect column - if they still exist!
1669 if (m_xLbTableDbColumn->find_text(sEntry) != -1)
1670 {
1671 m_xLbTableCol->append_text(sEntry);
1672 m_xLbTableDbColumn->remove_text(sEntry);
1673 }
1674 } while( n>=0 );
1675
1676 if (!m_xLbTableDbColumn->n_children())
1677 {
1678 m_xIbDbcolAllTo->set_sensitive( false );
1679 m_xIbDbcolOneTo->set_sensitive( false );
1680 }
1681 m_xIbDbcolOneFrom->set_sensitive(true);
1682 m_xIbDbcolAllFrom->set_sensitive(true);
1683 }
1684 m_xEdDbText->set_text( pNewData->sEdit );
1685
1686 sTmp = pNewData->sTmplNm;
1687 if( !sTmp.isEmpty() )
1688 m_xLbDbParaColl->set_active_text(sTmp);
1689 else
1690 m_xLbDbParaColl->set_active(0);
1691
1692 m_xTAutoFormat.reset();
1693 sTmp = pNewData->sTAutoFormatNm;
1694 if( !sTmp.isEmpty() )
1695 {
1696 // then load the AutoFormat file and look for Autoformat first
1697 SwTableAutoFormatTable aAutoFormatTable;
1698 aAutoFormatTable.Load();
1699 for( size_t nAutoFormat = aAutoFormatTable.size(); nAutoFormat; )
1700 if( sTmp == aAutoFormatTable[ --nAutoFormat ].GetName() )
1701 {
1702 m_xTAutoFormat.reset(new SwTableAutoFormat(aAutoFormatTable[nAutoFormat]));
1703 break;
1704 }
1705 }
1706
1707 m_xRbAsTable->set_active( pNewData->bIsTable );
1708 m_xRbAsField->set_active( pNewData->bIsField );
1709 m_xRbAsText->set_active( !pNewData->bIsTable && !pNewData->bIsField );
1710
1711 m_xCbTableHeadon->set_active( pNewData->bIsHeadlineOn );
1712 m_xRbHeadlColnms->set_active( !pNewData->bIsEmptyHeadln );
1713 m_xRbHeadlEmpty->set_active( pNewData->bIsEmptyHeadln );
1714 HeaderHdl(*m_xCbTableHeadon);
1715
1716 // now copy the user defined Numberformat strings to the
1717 // Shell. Then only these are available as ID
1718 for( size_t n = 0; n < aDBColumns.size() ; ++n )
1719 {
1720 SwInsDBColumn& rSet = *aDBColumns[ n ];
1721 for( size_t m = 0; m < pNewData->aDBColumns.size() ; ++m )
1722 {
1723 SwInsDBColumn& rGet = *pNewData->aDBColumns[ m ];
1724 if(rGet.sColumn == rSet.sColumn)
1725 {
1726 if( rGet.bHasFormat && !rGet.bIsDBFormat )
1727 {
1728 rSet.bIsDBFormat = false;
1729 rSet.nUsrNumFormat = rNFormatr.GetEntryKey( rGet.sUsrNumFormat,
1730 rGet.eUsrNumFormatLng );
1731 if( NUMBERFORMAT_ENTRY_NOT_FOUND == rSet.nUsrNumFormat )
1732 {
1733 sal_Int32 nCheckPos;
1734 SvNumFormatType nType;
1735 rNFormatr.PutEntry( rGet.sUsrNumFormat, nCheckPos, nType,
1736 rSet.nUsrNumFormat, rGet.eUsrNumFormatLng );
1737 }
1738 }
1739 break;
1740 }
1741 }
1742 }
1743
1744 // when the cursor is inside of a table, table must NEVER be selectable
1745 if( !m_xRbAsTable->get_sensitive() && m_xRbAsTable->get_active() )
1746 m_xRbAsField->set_active(true);
1747 break;
1748 }
1749 }
1750}
1751
1752/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
21
Calling 'Reference::get'
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205 if (aTmp.get()) {
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
3
Calling implicit copy constructor for 'VclPtr<AbstractSwAutoFormatDlg>'
4
Calling copy constructor for 'Reference<AbstractSwAutoFormatDlg>'
7
Returning from copy constructor for 'Reference<AbstractSwAutoFormatDlg>'
8
Returning from copy constructor for 'VclPtr<AbstractSwAutoFormatDlg>'
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
5
Assuming field 'm_pBody' is non-null
6
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
11.1
Field 'm_pBody' is non-null
)
12
Taking true branch
113 m_pBody->release();
13
Calling 'VclReferenceBase::release'
17
Returning; memory was released
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
22
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
14
Assuming the condition is true
15
Taking true branch
40 delete this;
16
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif