File: | home/maarten/src/libreoffice/core/include/tools/ref.hxx |
Warning: | line 56, column 30 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 "TableManager.hxx" | |||
21 | #include <ooxml/resourceids.hxx> | |||
22 | #include "TagLogger.hxx" | |||
23 | #include "DomainMapperTableHandler.hxx" | |||
24 | #include "DomainMapper_Impl.hxx" | |||
25 | #include "util.hxx" | |||
26 | ||||
27 | #include <tools/diagnose_ex.h> | |||
28 | ||||
29 | namespace writerfilter::dmapper | |||
30 | { | |||
31 | void TableManager::clearData() {} | |||
32 | ||||
33 | void TableManager::openCell(const css::uno::Reference<css::text::XTextRange>& rHandle, | |||
34 | const TablePropertyMapPtr& pProps) | |||
35 | { | |||
36 | #ifdef DBG_UTIL | |||
37 | TagLogger::getInstance().startElement("tablemanager.openCell"); | |||
38 | TagLogger::getInstance().chars(XTextRangeToString(rHandle)); | |||
39 | TagLogger::getInstance().endElement(); | |||
40 | #endif | |||
41 | ||||
42 | if (!mTableDataStack.empty()) | |||
43 | { | |||
44 | TableData::Pointer_t pTableData = mTableDataStack.top(); | |||
45 | ||||
46 | pTableData->addCell(rHandle, pProps); | |||
47 | } | |||
48 | } | |||
49 | ||||
50 | bool TableManager::isIgnore() const { return isRowEnd(); } | |||
51 | ||||
52 | sal_uInt32 TableManager::getGridBefore(sal_uInt32 nRow) | |||
53 | { | |||
54 | assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail ("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" , 54, __extension__ __PRETTY_FUNCTION__)); | |||
55 | if (nRow >= mTableDataStack.top()->getRowCount()) | |||
56 | return 0; | |||
57 | return mTableDataStack.top()->getRow(nRow)->getGridBefore(); | |||
58 | } | |||
59 | ||||
60 | sal_uInt32 TableManager::getCurrentGridBefore() | |||
61 | { | |||
62 | return mTableDataStack.top()->getCurrentRow()->getGridBefore(); | |||
63 | } | |||
64 | ||||
65 | void TableManager::setCurrentGridBefore(sal_uInt32 nSkipGrids) | |||
66 | { | |||
67 | mTableDataStack.top()->getCurrentRow()->setGridBefore(nSkipGrids); | |||
68 | } | |||
69 | ||||
70 | sal_uInt32 TableManager::getGridAfter(sal_uInt32 nRow) | |||
71 | { | |||
72 | assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail ("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" , 72, __extension__ __PRETTY_FUNCTION__)); | |||
73 | if (nRow >= mTableDataStack.top()->getRowCount()) | |||
74 | return 0; | |||
75 | return mTableDataStack.top()->getRow(nRow)->getGridAfter(); | |||
76 | } | |||
77 | ||||
78 | void TableManager::setCurrentGridAfter(sal_uInt32 nSkipGrids) | |||
79 | { | |||
80 | assert(isInTable())(static_cast <bool> (isInTable()) ? void (0) : __assert_fail ("isInTable()", "/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" , 80, __extension__ __PRETTY_FUNCTION__)); | |||
81 | mTableDataStack.top()->getCurrentRow()->setGridAfter(nSkipGrids); | |||
82 | } | |||
83 | ||||
84 | std::vector<sal_uInt32> TableManager::getCurrentGridSpans() | |||
85 | { | |||
86 | return mTableDataStack.top()->getCurrentRow()->getGridSpans(); | |||
87 | } | |||
88 | ||||
89 | void TableManager::setCurrentGridSpan(sal_uInt32 nGridSpan, bool bFirstCell) | |||
90 | { | |||
91 | mTableDataStack.top()->getCurrentRow()->setCurrentGridSpan(nGridSpan, bFirstCell); | |||
92 | } | |||
93 | ||||
94 | sal_uInt32 TableManager::findColumn(const sal_uInt32 nRow, const sal_uInt32 nCell) | |||
95 | { | |||
96 | RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow); | |||
97 | if (!pRow || nCell < pRow->getGridBefore() | |||
98 | || nCell >= pRow->getCellCount() - pRow->getGridAfter()) | |||
99 | { | |||
100 | return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF); | |||
101 | } | |||
102 | ||||
103 | // The gridSpans provide a one-based index, so add up all the spans of the PREVIOUS columns, | |||
104 | // and that result will provide the first possible zero-based number for the desired column. | |||
105 | sal_uInt32 nColumn = 0; | |||
106 | for (sal_uInt32 n = 0; n < nCell; ++n) | |||
107 | nColumn += pRow->getGridSpan(n); | |||
108 | return nColumn; | |||
109 | } | |||
110 | ||||
111 | sal_uInt32 TableManager::findColumnCell(const sal_uInt32 nRow, const sal_uInt32 nCol) | |||
112 | { | |||
113 | RowData::Pointer_t pRow = mTableDataStack.top()->getRow(nRow); | |||
114 | if (!pRow || nCol < pRow->getGridBefore()) | |||
115 | return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF); | |||
116 | ||||
117 | sal_uInt32 nCell = 0; | |||
118 | sal_uInt32 nGrids = 0; | |||
119 | // The gridSpans give us a one-based index, but requested column is zero-based - so keep that in mind. | |||
120 | const sal_uInt32 nMaxCell = pRow->getCellCount() - pRow->getGridAfter() - 1; | |||
121 | for (const auto& rSpan : pRow->getGridSpans()) | |||
122 | { | |||
123 | nGrids += rSpan; | |||
124 | if (nCol < nGrids) | |||
125 | return nCell; | |||
126 | ||||
127 | ++nCell; | |||
128 | if (nCell > nMaxCell) | |||
129 | break; | |||
130 | } | |||
131 | return SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF); // must be in gridAfter or invalid column request | |||
132 | } | |||
133 | ||||
134 | void TableManager::endOfRowAction() {} | |||
135 | ||||
136 | void TableManager::endOfCellAction() {} | |||
137 | ||||
138 | void TableManager::insertTableProps(const TablePropertyMapPtr& pProps) | |||
139 | { | |||
140 | #ifdef DBG_UTIL | |||
141 | TagLogger::getInstance().startElement("tablemanager.insertTableProps"); | |||
142 | #endif | |||
143 | ||||
144 | if (getTableProps() && getTableProps() != pProps) | |||
145 | getTableProps()->InsertProps(pProps.get()); | |||
146 | else | |||
147 | mState.setTableProps(pProps); | |||
148 | ||||
149 | #ifdef DBG_UTIL | |||
150 | TagLogger::getInstance().endElement(); | |||
151 | #endif | |||
152 | } | |||
153 | ||||
154 | void TableManager::insertRowProps(const TablePropertyMapPtr& pProps) | |||
155 | { | |||
156 | #ifdef DBG_UTIL | |||
157 | TagLogger::getInstance().startElement("tablemanager.insertRowProps"); | |||
158 | #endif | |||
159 | ||||
160 | if (getRowProps()) | |||
161 | getRowProps()->InsertProps(pProps.get()); | |||
162 | else | |||
163 | mState.setRowProps(pProps); | |||
164 | ||||
165 | #ifdef DBG_UTIL | |||
166 | TagLogger::getInstance().endElement(); | |||
167 | #endif | |||
168 | } | |||
169 | ||||
170 | void TableManager::cellProps(const TablePropertyMapPtr& pProps) | |||
171 | { | |||
172 | #ifdef DBG_UTIL | |||
173 | TagLogger::getInstance().startElement("tablemanager.cellProps"); | |||
174 | #endif | |||
175 | ||||
176 | if (getCellProps()) | |||
177 | getCellProps()->InsertProps(pProps.get()); | |||
178 | else | |||
179 | mState.setCellProps(pProps); | |||
180 | ||||
181 | #ifdef DBG_UTIL | |||
182 | TagLogger::getInstance().endElement(); | |||
183 | #endif | |||
184 | } | |||
185 | ||||
186 | void TableManager::tableExceptionProps(const TablePropertyMapPtr& pProps) | |||
187 | { | |||
188 | #ifdef DBG_UTIL | |||
189 | TagLogger::getInstance().startElement("tablemanager.tableExceptionProps"); | |||
190 | #endif | |||
191 | ||||
192 | if (getTableExceptionProps()) | |||
193 | getTableExceptionProps()->InsertProps(pProps.get()); | |||
194 | else | |||
195 | mState.setTableExceptionProps(pProps); | |||
196 | ||||
197 | #ifdef DBG_UTIL | |||
198 | TagLogger::getInstance().endElement(); | |||
199 | #endif | |||
200 | } | |||
201 | ||||
202 | void TableManager::utext(const sal_uInt8* data, std::size_t len) | |||
203 | { | |||
204 | // optimization: cell/row end characters are the last characters in a run | |||
205 | ||||
206 | if (len > 0) | |||
207 | { | |||
208 | sal_Unicode nChar = data[(len - 1) * 2] + (data[(len - 1) * 2 + 1] << 8); | |||
209 | if (nChar == 0x7) | |||
210 | handle0x7(); | |||
211 | } | |||
212 | } | |||
213 | ||||
214 | void TableManager::text(const sal_uInt8* data, std::size_t len) | |||
215 | { | |||
216 | // optimization: cell/row end characters are the last characters in a run | |||
217 | if (len > 0 && data[len - 1] == 0x7) | |||
218 | handle0x7(); | |||
219 | } | |||
220 | ||||
221 | void TableManager::handle0x7() | |||
222 | { | |||
223 | #ifdef DBG_UTIL | |||
224 | TagLogger::getInstance().startElement("tablemanager.handle0x7"); | |||
225 | #endif | |||
226 | ||||
227 | if (mnTableDepthNew < 1) | |||
228 | mnTableDepthNew = 1; | |||
229 | ||||
230 | if (isInCell()) | |||
231 | endCell(); | |||
232 | else | |||
233 | endRow(); | |||
234 | ||||
235 | #ifdef DBG_UTIL | |||
236 | TagLogger::getInstance().endElement(); | |||
237 | #endif | |||
238 | } | |||
239 | ||||
240 | bool TableManager::sprm(Sprm& rSprm) | |||
241 | { | |||
242 | bool bRet = true; | |||
243 | switch (rSprm.getId()) | |||
244 | { | |||
245 | case NS_ooxml::LN_tblDepth: | |||
246 | { | |||
247 | Value::Pointer_t pValue = rSprm.getValue(); | |||
248 | ||||
249 | cellDepth(pValue->getInt()); | |||
250 | } | |||
251 | break; | |||
252 | case NS_ooxml::LN_inTbl: | |||
253 | inCell(); | |||
254 | break; | |||
255 | case NS_ooxml::LN_tblCell: | |||
256 | endCell(); | |||
257 | break; | |||
258 | case NS_ooxml::LN_tblRow: | |||
259 | endRow(); | |||
260 | break; | |||
261 | default: | |||
262 | bRet = false; | |||
263 | } | |||
264 | return bRet; | |||
265 | } | |||
266 | ||||
267 | void TableManager::closeCell(const css::uno::Reference<css::text::XTextRange>& rHandle) | |||
268 | { | |||
269 | #ifdef DBG_UTIL | |||
270 | TagLogger::getInstance().startElement("tablemanager.closeCell"); | |||
271 | TagLogger::getInstance().chars(XTextRangeToString(rHandle)); | |||
272 | TagLogger::getInstance().endElement(); | |||
273 | #endif | |||
274 | ||||
275 | if (!mTableDataStack.empty()) | |||
276 | { | |||
277 | TableData::Pointer_t pTableData = mTableDataStack.top(); | |||
278 | ||||
279 | pTableData->endCell(rHandle); | |||
280 | ||||
281 | if (mpTableDataHandler) | |||
282 | mpTableDataHandler->getDomainMapperImpl().ClearPreviousParagraph(); | |||
283 | } | |||
284 | } | |||
285 | ||||
286 | void TableManager::ensureOpenCell(const TablePropertyMapPtr& pProps) | |||
287 | { | |||
288 | #ifdef DBG_UTIL | |||
289 | TagLogger::getInstance().startElement("tablemanager.ensureOpenCell"); | |||
290 | #endif | |||
291 | ||||
292 | if (!mTableDataStack.empty()) | |||
293 | { | |||
294 | TableData::Pointer_t pTableData = mTableDataStack.top(); | |||
295 | ||||
296 | if (pTableData != nullptr) | |||
297 | { | |||
298 | if (!pTableData->isCellOpen()) | |||
299 | openCell(getHandle(), pProps); | |||
300 | else | |||
301 | pTableData->insertCellProperties(pProps); | |||
302 | } | |||
303 | } | |||
304 | #ifdef DBG_UTIL | |||
305 | TagLogger::getInstance().endElement(); | |||
306 | #endif | |||
307 | } | |||
308 | ||||
309 | void TableManager::endParagraphGroup() | |||
310 | { | |||
311 | sal_Int32 nTableDepthDifference = mnTableDepthNew - mnTableDepth; | |||
312 | ||||
313 | TablePropertyMapPtr pEmptyProps; | |||
314 | ||||
315 | while (nTableDepthDifference > 0) | |||
| ||||
316 | { | |||
317 | ensureOpenCell(pEmptyProps); | |||
318 | startLevel(); | |||
319 | ||||
320 | --nTableDepthDifference; | |||
321 | } | |||
322 | while (nTableDepthDifference < 0) | |||
323 | { | |||
324 | endLevel(); | |||
325 | ||||
326 | ++nTableDepthDifference; | |||
327 | } | |||
328 | ||||
329 | mnTableDepth = mnTableDepthNew; | |||
330 | ||||
331 | if (mnTableDepth <= 0) | |||
332 | return; | |||
333 | ||||
334 | if (isRowEnd()) | |||
335 | { | |||
336 | endOfRowAction(); | |||
337 | mTableDataStack.top()->endRow(getRowProps()); | |||
338 | mState.resetRowProps(); | |||
339 | } | |||
340 | ||||
341 | else if (isInCell()) | |||
342 | { | |||
343 | ensureOpenCell(getCellProps()); | |||
344 | ||||
345 | if (mState.isCellEnd()) | |||
346 | { | |||
347 | endOfCellAction(); | |||
348 | closeCell(getHandle()); | |||
349 | } | |||
350 | } | |||
351 | mState.resetCellProps(); | |||
352 | } | |||
353 | ||||
354 | void TableManager::startParagraphGroup() | |||
355 | { | |||
356 | mState.resetCellSpecifics(); | |||
357 | mnTableDepthNew = 0; | |||
358 | } | |||
359 | ||||
360 | void TableManager::resolveCurrentTable() | |||
361 | { | |||
362 | #ifdef DBG_UTIL | |||
363 | TagLogger::getInstance().startElement("tablemanager.resolveCurrentTable"); | |||
364 | #endif | |||
365 | ||||
366 | if (mpTableDataHandler != nullptr) | |||
367 | { | |||
368 | try | |||
369 | { | |||
370 | TableData::Pointer_t pTableData = mTableDataStack.top(); | |||
371 | ||||
372 | unsigned int nRows = pTableData->getRowCount(); | |||
373 | ||||
374 | mpTableDataHandler->startTable(getTableProps()); | |||
375 | ||||
376 | for (unsigned int nRow = 0; nRow < nRows; ++nRow) | |||
377 | { | |||
378 | RowData::Pointer_t pRowData = pTableData->getRow(nRow); | |||
379 | ||||
380 | unsigned int nCells = pRowData->getCellCount(); | |||
381 | ||||
382 | mpTableDataHandler->startRow(pRowData->getProperties()); | |||
383 | ||||
384 | for (unsigned int nCell = 0; nCell < nCells; ++nCell) | |||
385 | { | |||
386 | mpTableDataHandler->startCell(pRowData->getCellStart(nCell), | |||
387 | pRowData->getCellProperties(nCell)); | |||
388 | ||||
389 | mpTableDataHandler->endCell(pRowData->getCellEnd(nCell)); | |||
390 | } | |||
391 | ||||
392 | mpTableDataHandler->endRow(); | |||
393 | } | |||
394 | ||||
395 | mpTableDataHandler->endTable(mTableDataStack.size() - 1, m_bTableStartsAtCellStart); | |||
396 | } | |||
397 | catch (css::uno::Exception const&) | |||
398 | { | |||
399 | TOOLS_WARN_EXCEPTION("writerfilter", "resolving of current table failed")do { css::uno::Any tools_warn_exception( DbgGetCaughtException () ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "writerfilter")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break ; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception )) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ( "writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" ":" "399" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" ":" "399" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception)) == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" ":" "399" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "resolving of current table failed" << " " << exceptionToString(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("writerfilter"), ("/home/maarten/src/libreoffice/core/writerfilter/source/dmapper/TableManager.cxx" ":" "399" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); } while (false); | |||
400 | } | |||
401 | } | |||
402 | mState.resetTableProps(); | |||
403 | clearData(); | |||
404 | ||||
405 | #ifdef DBG_UTIL | |||
406 | TagLogger::getInstance().endElement(); | |||
407 | #endif | |||
408 | } | |||
409 | ||||
410 | void TableManager::endLevel() | |||
411 | { | |||
412 | if (mpTableDataHandler != nullptr) | |||
413 | resolveCurrentTable(); | |||
414 | ||||
415 | // Store the unfinished row as it will be used for the next table | |||
416 | if (mbKeepUnfinishedRow) | |||
417 | mpUnfinishedRow = mTableDataStack.top()->getCurrentRow(); | |||
418 | mState.endLevel(); | |||
419 | mTableDataStack.pop(); | |||
420 | ||||
421 | #ifdef DBG_UTIL | |||
422 | TableData::Pointer_t pTableData; | |||
423 | ||||
424 | if (!mTableDataStack.empty()) | |||
425 | pTableData = mTableDataStack.top(); | |||
426 | ||||
427 | TagLogger::getInstance().startElement("tablemanager.endLevel"); | |||
428 | TagLogger::getInstance().attribute("level", mTableDataStack.size()); | |||
429 | ||||
430 | if (pTableData != nullptr) | |||
431 | TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no"); | |||
432 | ||||
433 | TagLogger::getInstance().endElement(); | |||
434 | #endif | |||
435 | } | |||
436 | ||||
437 | void TableManager::startLevel() | |||
438 | { | |||
439 | #ifdef DBG_UTIL | |||
440 | TableData::Pointer_t pTableData; | |||
441 | ||||
442 | if (!mTableDataStack.empty()) | |||
443 | pTableData = mTableDataStack.top(); | |||
444 | ||||
445 | TagLogger::getInstance().startElement("tablemanager.startLevel"); | |||
446 | TagLogger::getInstance().attribute("level", mTableDataStack.size()); | |||
447 | ||||
448 | if (pTableData != nullptr) | |||
449 | TagLogger::getInstance().attribute("openCell", pTableData->isCellOpen() ? "yes" : "no"); | |||
450 | ||||
451 | TagLogger::getInstance().endElement(); | |||
452 | #endif | |||
453 | ||||
454 | TableData::Pointer_t pTableData2(new TableData(mTableDataStack.size())); | |||
455 | ||||
456 | // If we have an unfinished row stored here, then push it to the new TableData | |||
457 | if (mpUnfinishedRow) | |||
458 | { | |||
459 | for (unsigned int i = 0; i < mpUnfinishedRow->getCellCount(); ++i) | |||
460 | { | |||
461 | pTableData2->addCell(mpUnfinishedRow->getCellStart(i), | |||
462 | mpUnfinishedRow->getCellProperties(i)); | |||
463 | pTableData2->endCell(mpUnfinishedRow->getCellEnd(i)); | |||
464 | pTableData2->getCurrentRow()->setCurrentGridSpan(mpUnfinishedRow->getGridSpan(i)); | |||
465 | } | |||
466 | pTableData2->getCurrentRow()->setGridBefore(mpUnfinishedRow->getGridBefore()); | |||
467 | pTableData2->getCurrentRow()->setGridAfter(mpUnfinishedRow->getGridAfter()); | |||
468 | mpUnfinishedRow.clear(); | |||
469 | } | |||
470 | ||||
471 | mTableDataStack.push(pTableData2); | |||
472 | mState.startLevel(); | |||
473 | } | |||
474 | ||||
475 | bool TableManager::isInTable() | |||
476 | { | |||
477 | bool bInTable = false; | |||
478 | if (!mTableDataStack.empty()) | |||
479 | bInTable = mTableDataStack.top()->getDepth() > 0; | |||
480 | return bInTable; | |||
481 | } | |||
482 | ||||
483 | void TableManager::handle(const css::uno::Reference<css::text::XTextRange>& rHandle) | |||
484 | { | |||
485 | #ifdef DBG_UTIL | |||
486 | TagLogger::getInstance().startElement("tablemanager.handle"); | |||
487 | TagLogger::getInstance().chars(XTextRangeToString(rHandle)); | |||
488 | TagLogger::getInstance().endElement(); | |||
489 | #endif | |||
490 | ||||
491 | setHandle(rHandle); | |||
492 | } | |||
493 | ||||
494 | void TableManager::setHandler(const tools::SvRef<DomainMapperTableHandler>& pTableDataHandler) | |||
495 | { | |||
496 | mpTableDataHandler = pTableDataHandler; | |||
497 | } | |||
498 | ||||
499 | void TableManager::endRow() | |||
500 | { | |||
501 | #ifdef DBG_UTIL | |||
502 | TagLogger::getInstance().element("tablemanager.endRow"); | |||
503 | #endif | |||
504 | TableData::Pointer_t pTableData = mTableDataStack.top(); | |||
505 | ||||
506 | // Add borderless w:gridBefore cell(s) to the row | |||
507 | sal_uInt32 nGridBefore = getCurrentGridBefore(); | |||
508 | if (pTableData && nGridBefore > 0 && pTableData->getCurrentRow()->getCellCount() > 0) | |||
509 | { | |||
510 | const css::uno::Reference<css::text::XTextRange>& xRowStart | |||
511 | = pTableData->getCurrentRow()->getCellStart(0); | |||
512 | if (xRowStart.is()) | |||
513 | { | |||
514 | try | |||
515 | { | |||
516 | // valid TextRange for table creation (not a nested table)? | |||
517 | xRowStart->getText()->createTextCursorByRange(xRowStart); | |||
518 | ||||
519 | for (unsigned int i = 0; i < nGridBefore; ++i) | |||
520 | { | |||
521 | css::table::BorderLine2 aBorderLine; | |||
522 | aBorderLine.Color = 0; | |||
523 | aBorderLine.InnerLineWidth = 0; | |||
524 | aBorderLine.OuterLineWidth = 0; | |||
525 | TablePropertyMapPtr pCellProperties(new TablePropertyMap); | |||
526 | pCellProperties->Insert(PROP_TOP_BORDER, css::uno::makeAny(aBorderLine)); | |||
527 | pCellProperties->Insert(PROP_LEFT_BORDER, css::uno::makeAny(aBorderLine)); | |||
528 | pCellProperties->Insert(PROP_BOTTOM_BORDER, css::uno::makeAny(aBorderLine)); | |||
529 | pCellProperties->Insert(PROP_RIGHT_BORDER, css::uno::makeAny(aBorderLine)); | |||
530 | pTableData->getCurrentRow()->addCell(xRowStart, pCellProperties, | |||
531 | /*bAddBefore=*/true); | |||
532 | } | |||
533 | } | |||
534 | catch (css::uno::Exception const&) | |||
535 | { | |||
536 | // don't add gridBefore cells in not valid TextRange | |||
537 | setCurrentGridBefore(0); | |||
538 | setCurrentGridSpan(getCurrentGridSpans().front() + nGridBefore, | |||
539 | /*bFirstCell=*/true); | |||
540 | } | |||
541 | } | |||
542 | } | |||
543 | ||||
544 | setRowEnd(true); | |||
545 | } | |||
546 | ||||
547 | void TableManager::endCell() | |||
548 | { | |||
549 | #ifdef DBG_UTIL | |||
550 | TagLogger::getInstance().element("tablemanager.endCell"); | |||
551 | #endif | |||
552 | ||||
553 | setCellEnd(true); | |||
554 | } | |||
555 | ||||
556 | void TableManager::inCell() | |||
557 | { | |||
558 | #ifdef DBG_UTIL | |||
559 | TagLogger::getInstance().element("tablemanager.inCell"); | |||
560 | #endif | |||
561 | setInCell(true); | |||
562 | ||||
563 | if (mnTableDepthNew < 1) | |||
564 | mnTableDepthNew = 1; | |||
565 | } | |||
566 | ||||
567 | void TableManager::cellDepth(sal_uInt32 nDepth) | |||
568 | { | |||
569 | #ifdef DBG_UTIL | |||
570 | TagLogger::getInstance().startElement("tablemanager.cellDepth"); | |||
571 | TagLogger::getInstance().attribute("depth", nDepth); | |||
572 | TagLogger::getInstance().endElement(); | |||
573 | #endif | |||
574 | ||||
575 | mnTableDepthNew = nDepth; | |||
576 | } | |||
577 | ||||
578 | void TableManager::setTableStartsAtCellStart(bool bTableStartsAtCellStart) | |||
579 | { | |||
580 | m_bTableStartsAtCellStart = bTableStartsAtCellStart; | |||
581 | } | |||
582 | ||||
583 | void TableManager::setCellLastParaAfterAutospacing(bool bIsAfterAutospacing) | |||
584 | { | |||
585 | m_bCellLastParaAfterAutospacing = bIsAfterAutospacing; | |||
586 | } | |||
587 | ||||
588 | TableManager::TableManager() | |||
589 | : mnTableDepthNew(0) | |||
590 | , mnTableDepth(0) | |||
591 | , mbKeepUnfinishedRow(false) | |||
592 | , m_bTableStartsAtCellStart(false) | |||
593 | { | |||
594 | setRowEnd(false); | |||
595 | setInCell(false); | |||
596 | setCellEnd(false); | |||
597 | m_bCellLastParaAfterAutospacing = false; | |||
598 | } | |||
599 | ||||
600 | TableManager::~TableManager() = default; | |||
601 | } | |||
602 | ||||
603 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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_WRITERFILTER_SOURCE_DMAPPER_TABLEDATA_HXX |
21 | #define INCLUDED_WRITERFILTER_SOURCE_DMAPPER_TABLEDATA_HXX |
22 | |
23 | #include <com/sun/star/text/XTextRange.hpp> |
24 | |
25 | #include "PropertyMap.hxx" |
26 | |
27 | #include <vector> |
28 | |
29 | namespace writerfilter::dmapper |
30 | { |
31 | |
32 | /** |
33 | Class containing the data to describe a table cell. |
34 | */ |
35 | class CellData final : public virtual SvRefBase |
36 | { |
37 | /** |
38 | Handle to start of cell. |
39 | */ |
40 | css::uno::Reference<css::text::XTextRange> mStart; |
41 | |
42 | /** |
43 | Handle to end of cell. |
44 | */ |
45 | css::uno::Reference<css::text::XTextRange> mEnd; |
46 | |
47 | /** |
48 | Pointer to properties of cell. |
49 | */ |
50 | TablePropertyMapPtr mpProps; |
51 | |
52 | bool mbOpen; |
53 | |
54 | sal_uInt32 m_nGridSpan; ///< number of grid columns in the parent table's table grid which this cell defines |
55 | |
56 | public: |
57 | typedef tools::SvRef<CellData> Pointer_t; |
58 | |
59 | CellData(css::uno::Reference<css::text::XTextRange> const & start, TablePropertyMapPtr pProps) |
60 | : mStart(start), mEnd(start), mpProps(pProps), mbOpen(true) |
61 | , m_nGridSpan(1) |
62 | { |
63 | } |
64 | |
65 | /** |
66 | Set the end handle of a cell. |
67 | |
68 | @param end the end handle of the cell |
69 | */ |
70 | void setEnd(css::uno::Reference<css::text::XTextRange> const & end) { mEnd = end; mbOpen = false; } |
71 | |
72 | /** |
73 | Adds properties to the cell. |
74 | |
75 | @param pProps the properties to add |
76 | */ |
77 | void insertProperties(TablePropertyMapPtr pProps) |
78 | { |
79 | if( mpProps ) |
80 | mpProps->InsertProps(pProps.get()); |
81 | else |
82 | mpProps = pProps; |
83 | } |
84 | |
85 | /** |
86 | Return start handle of the cell. |
87 | */ |
88 | const css::uno::Reference<css::text::XTextRange>& getStart() const { return mStart; } |
89 | |
90 | /** |
91 | Return end handle of the cell. |
92 | */ |
93 | const css::uno::Reference<css::text::XTextRange>& getEnd() const { return mEnd; } |
94 | |
95 | /** |
96 | Return properties of the cell. |
97 | */ |
98 | const TablePropertyMapPtr& getProperties() const { return mpProps; } |
99 | |
100 | bool isOpen() const { return mbOpen; } |
101 | |
102 | sal_uInt32 getGridSpan() const { return m_nGridSpan; } |
103 | void setGridSpan( sal_uInt32 nSpan ) { m_nGridSpan = nSpan; } |
104 | }; |
105 | |
106 | /** |
107 | Class to handle data of a table row. |
108 | */ |
109 | class RowData final : public virtual SvRefBase |
110 | { |
111 | typedef ::std::vector<CellData::Pointer_t> Cells; |
112 | |
113 | /** |
114 | the cell data of the row |
115 | */ |
116 | Cells mCells; |
117 | |
118 | /** |
119 | the properties of the row |
120 | */ |
121 | mutable TablePropertyMapPtr mpProperties; |
122 | |
123 | sal_uInt32 m_nGridBefore; ///< number of grid columns in the parent table's table grid which must be skipped before the contents of this table row are added to the parent table |
124 | sal_uInt32 m_nGridAfter; ///< number of grid columns in the parent table's table grid which shall be left after the last cell in the table row |
125 | |
126 | public: |
127 | typedef tools::SvRef<RowData> Pointer_t; |
128 | |
129 | RowData() |
130 | : m_nGridBefore(0) |
131 | , m_nGridAfter(0) |
132 | { |
133 | } |
134 | |
135 | RowData(const RowData& rRowData) |
136 | : SvRefBase(), mCells(rRowData.mCells), mpProperties(rRowData.mpProperties) |
137 | , m_nGridBefore(rRowData.m_nGridBefore) |
138 | , m_nGridAfter(rRowData.m_nGridAfter) |
139 | { |
140 | } |
141 | |
142 | /** |
143 | Add a cell to the row. |
144 | |
145 | @param start the start handle of the cell |
146 | @param end the end handle of the cell |
147 | @param pProps the properties of the cell |
148 | @param bAddBefore true: add an empty cell at beginning of the row for gridBefore |
149 | */ |
150 | void addCell(const css::uno::Reference<css::text::XTextRange>& start, TablePropertyMapPtr pProps, bool bAddBefore = false) |
151 | { |
152 | CellData::Pointer_t pCellData(new CellData(start, pProps)); |
153 | if (bAddBefore) |
154 | { |
155 | mCells.insert(mCells.begin(), pCellData); |
156 | mCells[0]->setEnd(start); |
157 | } |
158 | else |
159 | mCells.push_back(pCellData); |
160 | } |
161 | |
162 | void endCell(const css::uno::Reference<css::text::XTextRange>& end) |
163 | { |
164 | if (mCells.size() > 0) |
165 | mCells.back()->setEnd(end); |
166 | } |
167 | |
168 | bool isCellOpen() const |
169 | { |
170 | return mCells.size() > 0 && mCells.back()->isOpen(); |
171 | } |
172 | |
173 | /** |
174 | Add properties to the row. |
175 | |
176 | @param pProperties the properties to set |
177 | */ |
178 | void insertProperties(TablePropertyMapPtr pProperties) |
179 | { |
180 | if( pProperties ) |
181 | { |
182 | if( !mpProperties ) |
183 | mpProperties = pProperties; |
184 | else |
185 | mpProperties->InsertProps(pProperties.get()); |
186 | } |
187 | } |
188 | |
189 | /** |
190 | Add properties to the last cell of the row. |
191 | */ |
192 | void insertCellProperties(TablePropertyMapPtr pProps) |
193 | { |
194 | if (!mCells.empty()) |
195 | mCells.back()->insertProperties(pProps); |
196 | } |
197 | |
198 | /** |
199 | Return number of cells in the row. |
200 | */ |
201 | unsigned int getCellCount() const |
202 | { |
203 | return mCells.size(); |
204 | } |
205 | |
206 | /** |
207 | Return start handle of a cell in the row. |
208 | |
209 | @param i index of the cell |
210 | */ |
211 | const css::uno::Reference<css::text::XTextRange>& getCellStart(unsigned int i) const |
212 | { |
213 | return mCells[i]->getStart(); |
214 | } |
215 | |
216 | /** |
217 | Return end handle of a cell in the row. |
218 | |
219 | @param i index of the cell |
220 | */ |
221 | const css::uno::Reference<css::text::XTextRange>& getCellEnd(unsigned int i) const |
222 | { |
223 | return mCells[i]->getEnd(); |
224 | } |
225 | |
226 | /** |
227 | Return the properties of a cell in the row. |
228 | |
229 | @param i index of the cell |
230 | */ |
231 | TablePropertyMapPtr const & getCellProperties(unsigned int i) const |
232 | { |
233 | return mCells[i]->getProperties(); |
234 | } |
235 | |
236 | /** |
237 | Return properties of the row. |
238 | */ |
239 | const TablePropertyMapPtr& getProperties() const |
240 | { |
241 | return mpProperties; |
242 | } |
243 | |
244 | sal_uInt32 getGridBefore() const { return m_nGridBefore; } |
245 | void setGridBefore(sal_uInt32 nSkipGrids) { m_nGridBefore = nSkipGrids; } |
246 | sal_uInt32 getGridAfter() const { return m_nGridAfter; } |
247 | void setGridAfter(sal_uInt32 nSkipGrids) { m_nGridAfter = nSkipGrids; } |
248 | sal_uInt32 getGridSpan(sal_uInt32 i) { return mCells[i]->getGridSpan(); } |
249 | std::vector< sal_uInt32 > getGridSpans() |
250 | { |
251 | std::vector< sal_uInt32 > nRet; |
252 | for (auto const& aCell: mCells) |
253 | nRet.push_back(aCell->getGridSpan()); |
254 | return nRet; |
255 | } |
256 | void setCurrentGridSpan(sal_uInt32 nSpan, bool bFirstCell = false) |
257 | { |
258 | if ( mCells.size() ) |
259 | { |
260 | if ( bFirstCell ) |
261 | mCells.front()->setGridSpan(nSpan); |
262 | else |
263 | mCells.back()->setGridSpan(nSpan); |
264 | } |
265 | } |
266 | }; |
267 | |
268 | /** |
269 | Class that holds the data of a table. |
270 | */ |
271 | class TableData : public virtual SvRefBase |
272 | { |
273 | typedef RowData::Pointer_t RowPointer_t; |
274 | typedef ::std::vector<RowPointer_t> Rows; |
275 | |
276 | /** |
277 | the data of the rows of the table |
278 | */ |
279 | Rows mRows; |
280 | |
281 | /** |
282 | pointer to the data of the current row (while building up the table data). |
283 | */ |
284 | RowPointer_t mpRow; |
285 | |
286 | /** |
287 | depth of the current table in a hierarchy of tables |
288 | */ |
289 | unsigned int mnDepth; |
290 | |
291 | /** |
292 | initialize mpRow |
293 | */ |
294 | void newRow() { mpRow = RowPointer_t(new RowData()); } |
295 | |
296 | public: |
297 | typedef tools::SvRef<TableData> Pointer_t; |
298 | |
299 | explicit TableData(unsigned int nDepth) : mnDepth(nDepth) { newRow(); } |
300 | |
301 | /** |
302 | End the current row. |
303 | |
304 | Sets properties of the current row and pushes the row to the |
305 | back of the rows currently contained in the table. |
306 | |
307 | @param pProperties properties of the row to be ended |
308 | */ |
309 | void endRow(TablePropertyMapPtr pProperties) |
310 | { |
311 | mpRow->insertProperties(pProperties); |
312 | mRows.push_back(mpRow); |
313 | newRow(); |
314 | } |
315 | |
316 | /** |
317 | Add a cell to the current row. |
318 | |
319 | @param start start handle of the cell |
320 | @param end end handle of the cell |
321 | @param pProps properties of the cell |
322 | */ |
323 | void addCell(const css::uno::Reference<css::text::XTextRange>& start, TablePropertyMapPtr pProps) |
324 | { |
325 | mpRow->addCell(start, pProps); |
326 | } |
327 | |
328 | /** |
329 | End the current cell of the current row. |
330 | |
331 | @parm end end handle of the cell |
332 | */ |
333 | void endCell(const css::uno::Reference<css::text::XTextRange>& end) |
334 | { |
335 | mpRow->endCell(end); |
336 | } |
337 | |
338 | /** |
339 | Return if the current cell of the current row is open. |
340 | */ |
341 | bool isCellOpen() const |
342 | { |
343 | return mpRow->isCellOpen(); |
344 | } |
345 | |
346 | /** |
347 | Insert properties to the current cell of the current row. |
348 | |
349 | @param pProps the properties to add |
350 | */ |
351 | void insertCellProperties(TablePropertyMapPtr pProps) |
352 | { |
353 | mpRow->insertCellProperties(pProps); |
354 | } |
355 | |
356 | /** |
357 | Return number of rows in the table. |
358 | */ |
359 | unsigned int getRowCount() const |
360 | { |
361 | return mRows.size(); |
362 | } |
363 | |
364 | /** |
365 | Return depth of table in surrounding table hierarchy. |
366 | */ |
367 | unsigned int getDepth() const |
368 | { |
369 | return mnDepth; |
370 | } |
371 | |
372 | /** |
373 | Return row data of a certain row. |
374 | |
375 | @param i index of the row |
376 | */ |
377 | RowPointer_t const & getRow(unsigned int i) const |
378 | { |
379 | return mRows[i]; |
380 | } |
381 | |
382 | const RowPointer_t& getCurrentRow() const |
383 | { |
384 | return mpRow; |
385 | } |
386 | }; |
387 | |
388 | } |
389 | |
390 | |
391 | #endif // INCLUDED_WRITERFILTER_SOURCE_DMAPPER_RESOURCEMODEL_TABLEDATA_HXX |
392 | |
393 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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_TOOLS_REF_HXX | |||
20 | #define INCLUDED_TOOLS_REF_HXX | |||
21 | ||||
22 | #include <sal/config.h> | |||
23 | #include <cassert> | |||
24 | #include <tools/toolsdllapi.h> | |||
25 | #include <utility> | |||
26 | ||||
27 | /** | |||
28 | This implements similar functionality to boost::intrusive_ptr | |||
29 | */ | |||
30 | ||||
31 | namespace tools { | |||
32 | ||||
33 | /** T must be a class that extends SvRefBase */ | |||
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { | |||
35 | public: | |||
36 | SvRef(): pObj(nullptr) {} | |||
37 | ||||
38 | SvRef(SvRef&& rObj) noexcept | |||
39 | { | |||
40 | pObj = rObj.pObj; | |||
41 | rObj.pObj = nullptr; | |||
42 | } | |||
43 | ||||
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) | |||
45 | { | |||
46 | if (pObj != nullptr) pObj->AddNextRef(); | |||
47 | } | |||
48 | ||||
49 | SvRef(T * pObjP): pObj(pObjP) | |||
50 | { | |||
51 | if (pObj != nullptr) pObj->AddFirstRef(); | |||
52 | } | |||
53 | ||||
54 | ~SvRef() | |||
55 | { | |||
56 | if (pObj != nullptr) pObj->ReleaseRef(); | |||
| ||||
57 | } | |||
58 | ||||
59 | void clear() | |||
60 | { | |||
61 | if (pObj != nullptr) { | |||
62 | T * pRefObj = pObj; | |||
63 | pObj = nullptr; | |||
64 | pRefObj->ReleaseRef(); | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | SvRef & operator =(SvRef const & rObj) | |||
69 | { | |||
70 | if (rObj.pObj != nullptr) { | |||
71 | rObj.pObj->AddNextRef(); | |||
72 | } | |||
73 | T * pRefObj = pObj; | |||
74 | pObj = rObj.pObj; | |||
75 | if (pRefObj != nullptr) { | |||
76 | pRefObj->ReleaseRef(); | |||
77 | } | |||
78 | return *this; | |||
79 | } | |||
80 | ||||
81 | SvRef & operator =(SvRef && rObj) | |||
82 | { | |||
83 | if (pObj != nullptr) { | |||
84 | pObj->ReleaseRef(); | |||
85 | } | |||
86 | pObj = rObj.pObj; | |||
87 | rObj.pObj = nullptr; | |||
88 | return *this; | |||
89 | } | |||
90 | ||||
91 | bool is() const { return pObj != nullptr; } | |||
92 | ||||
93 | explicit operator bool() const { return is(); } | |||
94 | ||||
95 | T * get() const { return pObj; } | |||
96 | ||||
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } | |||
98 | ||||
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } | |||
100 | ||||
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } | |||
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } | |||
103 | ||||
104 | private: | |||
105 | T * pObj; | |||
106 | }; | |||
107 | ||||
108 | /** | |||
109 | * This implements similar functionality to std::make_shared. | |||
110 | */ | |||
111 | template<typename T, typename... Args> | |||
112 | SvRef<T> make_ref(Args&& ... args) | |||
113 | { | |||
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); | |||
115 | } | |||
116 | ||||
117 | } | |||
118 | ||||
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ | |||
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase | |||
121 | { | |||
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* | |||
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object | |||
124 | unsigned int nRefCount : 31; | |||
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields | |||
126 | unsigned int bNoDelete : 1; | |||
127 | ||||
128 | protected: | |||
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; | |||
130 | ||||
131 | public: | |||
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} | |||
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} | |||
134 | ||||
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } | |||
136 | ||||
137 | void RestoreNoDelete() | |||
138 | { bNoDelete = 1; } | |||
139 | ||||
140 | void AddNextRef() | |||
141 | { | |||
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); | |||
143 | ++nRefCount; | |||
144 | } | |||
145 | ||||
146 | void AddFirstRef() | |||
147 | { | |||
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); | |||
149 | if( bNoDelete ) | |||
150 | bNoDelete = 0; | |||
151 | ++nRefCount; | |||
152 | } | |||
153 | ||||
154 | void ReleaseRef() | |||
155 | { | |||
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); | |||
157 | if( --nRefCount == 0 && !bNoDelete) | |||
158 | { | |||
159 | // I'm not sure about the original purpose of this line, but right now | |||
160 | // it serves the purpose that anything that attempts to do an AddRef() | |||
161 | // after an object is deleted will trip an assert. | |||
162 | nRefCount = 1 << 30; | |||
163 | delete this; | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | unsigned int GetRefCount() const | |||
168 | { return nRefCount; } | |||
169 | }; | |||
170 | ||||
171 | template<typename T> | |||
172 | class SvCompatWeakBase; | |||
173 | ||||
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. | |||
175 | */ | |||
176 | template<typename T> | |||
177 | class SvCompatWeakHdl final : public SvRefBase | |||
178 | { | |||
179 | friend class SvCompatWeakBase<T>; | |||
180 | T* _pObj; | |||
181 | ||||
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} | |||
183 | ||||
184 | public: | |||
185 | void ResetWeakBase( ) { _pObj = nullptr; } | |||
186 | T* GetObj() { return _pObj; } | |||
187 | }; | |||
188 | ||||
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. | |||
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. | |||
191 | */ | |||
192 | template<typename T> | |||
193 | class SvCompatWeakBase | |||
194 | { | |||
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
196 | ||||
197 | public: | |||
198 | /** Does not use initializer due to compiler warnings, | |||
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. | |||
200 | */ | |||
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } | |||
202 | ||||
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } | |||
204 | ||||
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } | |||
206 | }; | |||
207 | ||||
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. | |||
209 | */ | |||
210 | template<typename T> | |||
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef | |||
212 | { | |||
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
214 | public: | |||
215 | SvCompatWeakRef( ) {} | |||
216 | SvCompatWeakRef( T* pObj ) | |||
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } | |||
218 | #if defined(__COVERITY__) | |||
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} | |||
220 | #endif | |||
221 | SvCompatWeakRef& operator = ( T * pObj ) | |||
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } | |||
223 | bool is() const | |||
224 | { return _xHdl.is() && _xHdl->GetObj(); } | |||
225 | explicit operator bool() const { return is(); } | |||
226 | T* operator -> () const | |||
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
228 | operator T* () const | |||
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
230 | }; | |||
231 | ||||
232 | #endif | |||
233 | ||||
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |