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