Line data Source code
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 :
10 : #include "columniterator.hxx"
11 : #include "column.hxx"
12 : #include "document.hxx"
13 : #include "table.hxx"
14 :
15 : #include <osl/diagnose.h>
16 :
17 294846 : ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScColumn& rCol, SCROW nStartRow, SCROW nEndRow) :
18 : mrCellTextAttrs(rCol.maCellTextAttrs),
19 : mnEnd(static_cast<size_t>(nEndRow)),
20 : mnCurPos(0),
21 : miBlockCur(mrCellTextAttrs.begin()),
22 294846 : miBlockEnd(mrCellTextAttrs.end())
23 : {
24 294846 : init(nStartRow, nEndRow);
25 294846 : }
26 :
27 6 : ScColumnTextWidthIterator::ScColumnTextWidthIterator(ScDocument& rDoc, const ScAddress& rStartPos, SCROW nEndRow) :
28 12 : mrCellTextAttrs(rDoc.maTabs[rStartPos.Tab()]->aCol[rStartPos.Col()].maCellTextAttrs),
29 : mnEnd(static_cast<size_t>(nEndRow)),
30 : mnCurPos(0),
31 : miBlockCur(mrCellTextAttrs.begin()),
32 18 : miBlockEnd(mrCellTextAttrs.end())
33 : {
34 6 : init(rStartPos.Row(), nEndRow);
35 6 : }
36 :
37 1879 : void ScColumnTextWidthIterator::next()
38 : {
39 1879 : ++miDataCur;
40 1879 : ++mnCurPos;
41 :
42 1879 : if (miDataCur != miDataEnd)
43 : {
44 : // Stil in the same block. We're good.
45 1327 : checkEndRow();
46 1327 : return;
47 : }
48 :
49 : // Move to the next block.
50 1104 : for (++miBlockCur; miBlockCur != miBlockEnd; ++miBlockCur)
51 : {
52 567 : if (miBlockCur->type != sc::element_type_celltextattr)
53 : {
54 : // We don't iterator over this block.
55 552 : mnCurPos += miBlockCur->size;
56 552 : continue;
57 : }
58 :
59 15 : getDataIterators(0);
60 15 : checkEndRow();
61 15 : return;
62 : }
63 :
64 : // Reached the end.
65 : OSL_ASSERT(miBlockCur == miBlockEnd);
66 : }
67 :
68 296731 : bool ScColumnTextWidthIterator::hasCell() const
69 : {
70 296731 : return miBlockCur != miBlockEnd;
71 : }
72 :
73 1880 : SCROW ScColumnTextWidthIterator::getPos() const
74 : {
75 : OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
76 1880 : return static_cast<SCROW>(mnCurPos);
77 : }
78 :
79 0 : sal_uInt16 ScColumnTextWidthIterator::getValue() const
80 : {
81 : OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
82 0 : return miDataCur->mnTextWidth;
83 : }
84 :
85 1852 : void ScColumnTextWidthIterator::setValue(sal_uInt16 nVal)
86 : {
87 : OSL_ASSERT(miBlockCur != miBlockEnd && miDataCur != miDataEnd);
88 1852 : miDataCur->mnTextWidth = nVal;
89 1852 : }
90 :
91 294852 : void ScColumnTextWidthIterator::init(SCROW nStartRow, SCROW nEndRow)
92 : {
93 294852 : if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
94 0 : miBlockCur = miBlockEnd;
95 :
96 294852 : size_t nStart = static_cast<size_t>(nStartRow);
97 :
98 : // Locate the start row position.
99 294852 : size_t nBlockStart = 0, nBlockEnd = 0;
100 296609 : for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
101 : {
102 296609 : nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
103 296609 : if (nBlockStart <= nStart && nStart < nBlockEnd)
104 : {
105 : // Initial block is found!
106 294852 : break;
107 : }
108 : }
109 :
110 294852 : if (miBlockCur == miBlockEnd)
111 : // Initial block not found for whatever reason... Bail out.
112 0 : return;
113 :
114 : // Locate the initial row position within this block.
115 294852 : if (miBlockCur->type == sc::element_type_celltextattr)
116 : {
117 : // This block stores text widths for non-empty cells.
118 842 : size_t nOffsetInBlock = nStart - nBlockStart;
119 842 : mnCurPos = nStart;
120 842 : getDataIterators(nOffsetInBlock);
121 842 : checkEndRow();
122 842 : return;
123 : }
124 :
125 : // Current block is not of ushort type. Skip to the next block.
126 294010 : nBlockStart = nBlockEnd;
127 294010 : ++miBlockCur;
128 :
129 : // Look for the first ushort block.
130 294010 : for (; miBlockCur != miBlockEnd; ++miBlockCur, nBlockStart = nBlockEnd)
131 : {
132 123 : nBlockEnd = nBlockStart + miBlockCur->size; // non-inclusive end point.
133 123 : if (miBlockCur->type != sc::element_type_celltextattr)
134 0 : continue;
135 :
136 : // Found!
137 123 : mnCurPos = nBlockStart;
138 123 : getDataIterators(0);
139 123 : checkEndRow();
140 123 : return;
141 : }
142 :
143 : // Not found.
144 : OSL_ASSERT(miBlockCur == miBlockEnd);
145 : }
146 :
147 980 : void ScColumnTextWidthIterator::getDataIterators(size_t nOffsetInBlock)
148 : {
149 : OSL_ENSURE(miBlockCur != miBlockEnd, "block is at end position");
150 : #if 0
151 : // Does not compile
152 : OSL_ENSURE(miBlockCur->type == sc::celltextattr_block,
153 : "wrong block type - unsigned short block expected.");
154 : #endif
155 980 : miDataCur = sc::celltextattr_block::begin(*miBlockCur->data);
156 980 : miDataEnd = sc::celltextattr_block::end(*miBlockCur->data);
157 :
158 980 : std::advance(miDataCur, nOffsetInBlock);
159 980 : }
160 :
161 2307 : void ScColumnTextWidthIterator::checkEndRow()
162 : {
163 2307 : if (mnCurPos <= mnEnd)
164 : // We're still good.
165 4187 : return;
166 :
167 : // We're below the end position. End the iteration.
168 427 : miBlockCur = miBlockEnd;
169 156 : }
170 :
171 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|