1 diff -u -r source/pristine.filter/html/htmlpars.cxx source/filter/html/htmlpars.cxx
2 --- sc/source/filter/html/htmlpars.cxx
3 +++ sc/source/filter/html/htmlpars.cxx
6 using namespace ::com::sun::star;
9 + * Table to track which cells are used, and hence locked,
10 + * replacing old, horribly slow ScRangeList with N^2 behavior.
12 +class ScHTMLLockTable {
14 + struct ScAddressHashFunc : public std::unary_function< const ScAddress &, size_t >
16 + size_t operator() (const ScAddress &addr) const
18 + return static_cast< UINT16 >( addr.Row() ) ^ (static_cast< UINT8 >( addr.Col() ) << 16);
21 + std::hash_map<ScAddress, bool, ScAddressHashFunc> maIndividualCells;
22 + ScRangeList maRangeList;
29 + bool IsEmpty( const ScAddress &rAddr ) const
31 + if( maIndividualCells.find( rAddr ) != maIndividualCells.end() )
33 + return maRangeList.Find( rAddr ) == NULL;
36 + void AddRange( const ScRange &rRange )
38 + if( rRange.aStart == rRange.aEnd )
41 + fprintf( stderr, "Single cell\n");
43 + maIndividualCells.insert( std::pair<ScAddress, bool>( rRange.aStart, true ) );
48 + fprintf (stderr, "Multi-cell: %d, %d -> %d, %d\n",
49 + (int) rRange.aStart.Col(), (int) rRange.aStart.Row(),
50 + (int) rRange.aEnd.Col(), (int) rRange.aEnd.Row()); */
52 + maRangeList.Append( rRange );
55 + ScHTMLSize GetSpan( const ScAddress &rAddr ) const
57 + if( maIndividualCells.find( rAddr ) != maIndividualCells.end() )
58 + return ScHTMLSize (1, 1);
60 + ScRange *pRange = maRangeList.Find( rAddr );
61 + if( pRange == NULL )
62 + return ScHTMLSize (1, 1);
64 + return ScHTMLSize( pRange->aEnd.Col() - pRange->aStart.Col() + 1,
65 + pRange->aEnd.Row() - pRange->aStart.Row() + 1 );
67 + sal_uInt32 Count() const
69 + return maRangeList.Count();
71 + void AppendRange( ScAddress aPos, const ScHTMLSize &rSpanSize,
72 + ScRange &rInsertedRange)
74 + while( !IsEmpty( aPos ) )
77 + rInsertedRange = ScRange( aPos );
78 + rInsertedRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 );
80 + // Scan horizontally to find ranges that vertically overlap with us
81 + // and shrink them to move them up - this applies only to ranges,
82 + // individual cells will be to the left and/or above us and can't
83 + // be handled here...
84 + if( maRangeList.Intersects( rInsertedRange ) )
86 + // This is a highly uncommon case:
87 + // we care only about ranges above us, thus use a lame algorithm:
88 + // check each cell in the first row, and shrink upwards.
89 + for( ScAddress aAddr( aPos ); aAddr.Col() < rInsertedRange.aEnd.Col(); aAddr.IncCol() )
92 + if( ( pRange = maRangeList.Find( aAddr ) ) != NULL )
93 + pRange->aEnd.SetRow( aPos.Row() - 1 );
98 + AddRange (rInsertedRange);
103 SV_IMPL_VARARR_SORT( ScHTMLColOffset, ULONG );
105 @@ -1971,6 +2061,7 @@
106 mpParentTable( &rParentTable ),
107 maTableId( rParentTable.maTableId.mrnUnusedId ),
108 maTableItemSet( rParentTable.GetCurrItemSet() ),
109 + mpLockTable( new ScHTMLLockTable() ),
110 mrEditEngine( rParentTable.mrEditEngine ),
111 mrEEParseList( rParentTable.mrEEParseList ),
112 mpCurrEntryList( 0 ),
113 @@ -2010,6 +2101,7 @@
115 maTableId( rnUnusedId ),
116 maTableItemSet( rPool ),
117 + mpLockTable( new ScHTMLLockTable() ),
118 mrEditEngine( rEditEngine ),
119 mrEEParseList( rEEParseList ),
120 mpCurrEntryList( 0 ),
121 @@ -2028,6 +2120,7 @@
123 ScHTMLTable::~ScHTMLTable()
125 + delete mpLockTable;
128 const SfxItemSet& ScHTMLTable::GetCurrItemSet() const
129 @@ -2038,10 +2131,7 @@
131 ScHTMLSize ScHTMLTable::GetSpan( const ScHTMLPos& rCellPos ) const
133 - ScHTMLSize aSpan( 1, 1 );
134 - if( ScRange* pRange = maLockList.Find( rCellPos.MakeAddr() ) )
135 - aSpan.Set( pRange->aEnd.Col() - pRange->aStart.Col() + 1, pRange->aEnd.Row() - pRange->aStart.Row() + 1 );
137 + return mpLockTable->GetSpan( rCellPos.MakeAddr() );
140 ScHTMLTable* ScHTMLTable::FindNestedTable( ScHTMLTableId nTableId ) const
141 @@ -2435,24 +2525,12 @@
143 void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize )
147 + mpLockTable->AppendRange( maCurrCell.MakeAddr(), rSpanSize, aNewRange );
149 - // find an unused cell
150 - while( (pRange = maLockList.Find( maCurrCell.MakeAddr() )) != 0 )
151 - maCurrCell.mnCol = pRange->aEnd.Col() + 1;
152 + maCurrCell.mnCol = aNewRange.aStart.Col();
153 mpCurrEntryList = &maEntryMap[ maCurrCell ];
155 - // try to find collisions, shrink existing ranges
156 - SCCOL nColEnd = maCurrCell.mnCol + rSpanSize.mnCols;
157 - for( ScAddress aAddr( maCurrCell.MakeAddr() ); aAddr.Col() < nColEnd; aAddr.IncCol() )
158 - if( (pRange = maLockList.Find( aAddr )) != 0 )
159 - pRange->aEnd.SetRow( maCurrCell.mnRow - 1 );
161 - // insert the new range into the lock list
162 - ScRange aNewRange( maCurrCell.MakeAddr() );
163 - aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 );
164 - maLockList.Append( aNewRange );
167 maSize.mnCols = ::std::max< SCCOL >( maSize.mnCols, aNewRange.aEnd.Col() + 1 );
168 maSize.mnRows = ::std::max< SCROW >( maSize.mnRows, aNewRange.aEnd.Row() + 1 );
169 @@ -2474,6 +2552,35 @@
174 + if (maCurrCell.mnRow > 0) {
175 + // Try and back-merge the lock-list to avoid N^2 lookups
176 + SCCOL nColIdx = Min (0, maCurrCell.mnCol - 1);
177 + ScAddress aLastAddr = maCurrCell.MakeAddr();
178 + ScAddress aThisAddr = maCurrCell.MakeAddr();
179 + aLastAddr.IncRow( -1 );
180 + aLastAddr.SetCol( nColIdx );
181 + aThisAddr.SetCol( nColIdx );
182 + ScRange *pLastRange = maLockList.Find (aLastAddr);
183 + ScRange *pThisRange = maLockList.Find (aThisAddr);
185 + fprintf (stderr, "Last : null\n");
187 + fprintf (stderr, "Last: %d, %d -> %d, %d\n",
188 + pLastRange->aStart.Col(), pLastRange->aStart.Row(),
189 + pLastRange->aEnd.Col(), pLastRange->aEnd.Row());
191 + fprintf (stderr, "This : null\n");
193 + fprintf (stderr, "This: %d, %d -> %d, %d\n",
194 + pThisRange->aStart.Col(), pThisRange->aStart.Row(),
195 + pThisRange->aEnd.Col(), pThisRange->aEnd.Row());
196 + fprintf (stderr, "Lock list: %d long\n", maLockList.Count());
198 + if (mpLockTable->Count() > 0)
199 + fprintf (stderr, "Lock list: %d long\n", (int)mpLockTable->Count());
202 mpRowItemSet.reset();
204 mbRowOn = mbDataOn = false;
205 @@ -2594,15 +2699,15 @@
207 for( aAddr.SetCol( 0 ); aAddr.Col() < maSize.mnCols; aAddr.IncCol() )
209 - if( !maLockList.Find( aAddr ) )
210 + if( mpLockTable->IsEmpty( aAddr ) )
212 // create a range for the lock list (used to calc. cell span)
213 ScRange aRange( aAddr );
215 aRange.aEnd.IncCol();
216 - while( (aRange.aEnd.Col() < maSize.mnCols) && !maLockList.Find( aRange.aEnd ) );
217 + while( (aRange.aEnd.Col() < maSize.mnCols) && mpLockTable->IsEmpty( aRange.aEnd ) );
218 aRange.aEnd.IncCol( -1 );
219 - maLockList.Append( aRange );
220 + mpLockTable->AddRange( aRange );
222 // insert a dummy entry
223 ScHTMLEntryPtr pEntry = CreateEntry();
226 diff -u -r source/pristine.filter/inc/htmlpars.hxx source/filter/inc/htmlpars.hxx
227 --- sc/source/filter/inc/htmlpars.hxx
228 +++ sc/source/filter/inc/htmlpars.hxx
231 // ----------------------------------------------------------------------------
233 +class ScHTMLLockTable;
235 class ScHTMLTableMap;
237 /** Stores data for one table in an HTML document.
239 SfxItemSet maTableItemSet; /// Items for the entire table.
240 SfxItemSetPtr mpRowItemSet; /// Items for the current table row.
241 SfxItemSetPtr mpDataItemSet; /// Items for the current cell.
242 - ScRangeList maLockList; /// Locked cells (needed for merged cells).
243 + ScHTMLLockTable *mpLockTable; /// Locked cells (needed for merged cells).
244 EditEngine& mrEditEngine; /// Edit engine (from ScEEParser).
245 ScEEParseList& mrEEParseList; /// List that owns the parse entries (from ScEEParser).
246 ScHTMLEntryMap maEntryMap; /// List of entries for each cell.