xref: /aoo42x/main/sc/inc/column.hxx (revision b4df81e3)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SC_COLUMN_HXX
25 #define SC_COLUMN_HXX
26 
27 #include "markarr.hxx"
28 #include "global.hxx"
29 #include "address.hxx"
30 #include "rangenam.hxx"
31 #include <tools/solar.h>
32 
33 #include <set>
34 
35 class Fraction;
36 class OutputDevice;
37 class Rectangle;
38 class SfxBroadcaster;
39 class SfxItemPoolCache;
40 class SfxItemSet;
41 class SvtListener;
42 class SfxPoolItem;
43 class SfxStyleSheetBase;
44 class SvxBorderLine;
45 class SvxBoxInfoItem;
46 class SvxBoxItem;
47 
48 class ScAttrIterator;
49 class ScAttrArray;
50 class ScBaseCell;
51 class ScDocument;
52 class ScFormulaCell;
53 class ScMarkData;
54 class ScPatternAttr;
55 class ScStyleSheet;
56 class SvtBroadcaster;
57 class TypedScStrCollection;
58 class ScProgress;
59 class ScPostIt;
60 struct ScFunctionData;
61 struct ScLineFlags;
62 struct ScMergePatternState;
63 class ScDPTableDataCache;
64 class ScFlatBoolRowSegments;
65 
66 #define COLUMN_DELTA	4
67 
68 
69 struct ScNeededSizeOptions
70 {
71 	const ScPatternAttr*	pPattern;
72 	sal_Bool					bFormula;
73 	sal_Bool					bSkipMerged;
74 	sal_Bool					bGetFont;
75 	sal_Bool					bTotalSize;
76 
77 	ScNeededSizeOptions()
78 	{
79 		pPattern = NULL;
80 		bFormula = sal_False;
81 		bSkipMerged = sal_True;
82 		bGetFont = sal_True;
83 		bTotalSize = sal_False;
84 	}
85 };
86 
87 struct ColEntry
88 {
89 	SCROW		nRow;
90 	ScBaseCell*	pCell;
91 };
92 
93 
94 class ScColumn
95 {
96 private:
97 	SCCOL			nCol;
98 	SCTAB			nTab;
99 
100 	SCSIZE			nCount;
101 	SCSIZE			nLimit;
102 	ColEntry*		pItems;
103 
104 	ScAttrArray*	pAttrArray;
105 	ScDocument*		pDocument;
106 
107 friend class ScDocument;					// fuer FillInfo
108 friend class ScDocumentIterator;
109 friend class ScValueIterator;
110 friend class ScHorizontalValueIterator;
111 friend class ScDBQueryDataIterator;
112 friend class ScColumnIterator;
113 friend class ScQueryCellIterator;
114 friend class ScMarkedDataIter;
115 friend class ScCellIterator;
116 friend class ScHorizontalCellIterator;
117 friend class ScHorizontalAttrIterator;
118 
119 public:
120 static sal_Bool bDoubleAlloc;			// fuer Import: Groesse beim Allozieren verdoppeln
121 
122 public:
123 				ScColumn();
124 				~ScColumn();
125 
126 	void		Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc);
127 
128 	sal_Bool 		Search( SCROW nRow, SCSIZE& nIndex ) const;
129 	ScBaseCell*	GetCell( SCROW nRow ) const;
130 	void		Insert( SCROW nRow, ScBaseCell* pCell );
131 	void		Insert( SCROW nRow, sal_uLong nFormatIndex, ScBaseCell* pCell );
132 	void		Append( SCROW nRow, ScBaseCell* pCell );
133 	void 		Delete( SCROW nRow );
134 	void		DeleteAtIndex( SCSIZE nIndex );
135 	void 	    FreeAll();
136 	void		Resize( SCSIZE nSize );
137 	void		SwapRow( SCROW nRow1, SCROW nRow2 );
138 	void		SwapCell( SCROW nRow, ScColumn& rCol);
139 
140 //UNUSED2009-05 sal_Bool		HasLines( SCROW nRow1, SCROW nRow2, Rectangle& rSizes,
141 //UNUSED2009-05 			sal_Bool bLeft, sal_Bool bRight ) const;
142     bool        HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const;
143 	sal_Bool		HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const;
144 	sal_Bool		ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
145 								SCCOL& rPaintCol, SCROW& rPaintRow,
146 								sal_Bool bRefresh, sal_Bool bAttrs );
147 
148 	sal_Bool		IsEmptyVisData(sal_Bool bNotes) const;		// ohne Broadcaster
149 	sal_Bool		IsEmptyData() const;
150 	sal_Bool		IsEmptyAttr() const;
151 	sal_Bool		IsEmpty() const;
152 
153 				// nur Daten:
154 	sal_Bool		IsEmptyBlock(SCROW nStartRow, SCROW nEndRow, bool bIgnoreNotes = false) const;
155 	SCSIZE	    GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const;
156 	sal_Bool		HasDataAt(SCROW nRow) const;
157 	sal_Bool		HasVisibleDataAt(SCROW nRow) const;
158     SCROW		GetFirstDataPos() const;
159 	SCROW		GetLastDataPos() const;
160 	SCROW		GetLastVisDataPos(sal_Bool bNotes) const;				// ohne Broadcaster
161 	SCROW		GetFirstVisDataPos(sal_Bool bNotes) const;
162 	sal_Bool 		GetPrevDataPos(SCROW& rRow) const;
163 	sal_Bool 		GetNextDataPos(SCROW& rRow) const;
164 	void		FindDataAreaPos(SCROW& rRow, long nMovY) const;	// (ohne Broadcaster)
165 	void		FindUsed( SCROW nStartRow, SCROW nEndRow, sal_Bool* pUsed ) const;
166 
167 	SCSIZE		VisibleCount( SCROW nStartRow, SCROW nEndRow ) const;
168 
169 	sal_uInt16		GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const;
170 	sal_Bool		HasSelectionMatrixFragment(const ScMarkData& rMark) const;
171 
172     sal_Bool        GetFirstVisibleAttr( SCROW& rFirstRow ) const;
173     sal_Bool        GetLastVisibleAttr( SCROW& rLastRow ) const;
174 	sal_Bool		HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const;
175 	sal_Bool		IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow = 0,
176 									SCROW nEndRow = MAXROW ) const;
177 	sal_Bool		IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const;
178 
179 	sal_Bool		TestInsertCol( SCROW nStartRow, SCROW nEndRow) const;
180 	sal_Bool		TestInsertRow( SCSIZE nSize ) const;
181 	void		InsertRow( SCROW nStartRow, SCSIZE nSize );
182 	void		DeleteRow( SCROW nStartRow, SCSIZE nSize );
183     void        DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDelFlag );
184     void        DeleteArea(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nDelFlag );
185     void        CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, sal_Bool bKeepScenarioFlags, sal_Bool bCloneNoteCaptions);
186 	void		CopyFromClip(SCROW nRow1, SCROW nRow2, long nDy,
187 								sal_uInt16 nInsFlag, sal_Bool bAsLink, sal_Bool bSkipAttrForEmpty, ScColumn& rColumn);
188 	void		StartListeningInArea( SCROW nRow1, SCROW nRow2 );
189 	void		BroadcastInArea( SCROW nRow1, SCROW nRow2 );
190 
191 	void		RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow );
192 
193 				//	Markierung von diesem Dokument
194 	void		MixMarked( const ScMarkData& rMark, sal_uInt16 nFunction,
195 							sal_Bool bSkipEmpty, ScColumn& rSrcCol );
196 	void		MixData( SCROW nRow1, SCROW nRow2, sal_uInt16 nFunction, sal_Bool bSkipEmpty,
197 							ScColumn& rSrcCol );
198 
199 	ScFormulaCell*	CreateRefCell( ScDocument* pDestDoc, const ScAddress& rDestPos,
200 									SCSIZE nIndex, sal_uInt16 nFlags ) const;
201 
202 	ScAttrIterator* CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const;
203 
204 	SCCOL		GetCol() const { return nCol; }
205 
206 				//	UpdateSelectionFunction: Mehrfachselektion
207 	void		UpdateSelectionFunction( const ScMarkData& rMark,
208 									ScFunctionData& rData,
209                                     ScFlatBoolRowSegments& rHiddenRows,
210 									sal_Bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow );
211 	void		UpdateAreaFunction( ScFunctionData& rData,
212                                     ScFlatBoolRowSegments& rHiddenRows,
213 									SCROW nStartRow, SCROW nEndRow );
214 
215 	void		CopyToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
216 								ScColumn& rColumn, const ScMarkData* pMarkData = NULL,
217 								sal_Bool bAsLink = sal_False );
218 	void		UndoToColumn(SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, sal_Bool bMarked,
219 								ScColumn& rColumn, const ScMarkData* pMarkData = NULL );
220 
221 	void		CopyScenarioFrom( const ScColumn& rSrcCol );
222 	void		CopyScenarioTo( ScColumn& rDestCol ) const;
223 	sal_Bool		TestCopyScenarioTo( const ScColumn& rDestCol ) const;
224 	void		MarkScenarioIn( ScMarkData& rDestMark ) const;
225 
226 	void		CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const;
227 
228 	void		SwapCol(ScColumn& rCol);
229 	void		MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol);
230 
231 	sal_Bool		HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst) const;
232 
233 				//	sal_True = Zahlformat gesetzt
234 	sal_Bool		SetString( SCROW nRow, SCTAB nTab, const String& rString,
235 						   formula::FormulaGrammar::AddressConvention conv = formula::FormulaGrammar::CONV_OOO,
236                            SvNumberFormatter* pFormatter = NULL,
237                            bool bDetectNumberFormat = true );
238 	void		SetValue( SCROW nRow, const double& rVal);
239 	void		SetError( SCROW nRow, const sal_uInt16 nError);
240 
241 	void		GetString( SCROW nRow, String& rString ) const;
242 	void		GetInputString( SCROW nRow, String& rString ) const;
243 	double		GetValue( SCROW nRow ) const;
244 	void		GetFormula( SCROW nRow, String& rFormula,
245 							sal_Bool bAsciiExport = sal_False ) const;
246 	CellType	GetCellType( SCROW nRow ) const;
247 	SCSIZE		GetCellCount() const { return nCount; }
248 	sal_uLong		GetWeightedCount() const;
249 	sal_uLong		GetCodeCount() const;		// RPN-Code in Formeln
250 	sal_uInt16		GetErrCode( SCROW nRow ) const;
251 
252 	sal_Bool		HasStringData( SCROW nRow ) const;
253 	sal_Bool		HasValueData( SCROW nRow ) const;
254 //UNUSED2009-05 sal_uInt16		GetErrorData( SCROW nRow) const;
255 	sal_Bool		HasStringCells( SCROW nStartRow, SCROW nEndRow ) const;
256 
257     /** Returns the pointer to a cell note object at the passed row. */
258     ScPostIt*   GetNote( SCROW nRow );
259     /** Sets the passed cell note object at the passed row. Takes ownership! */
260     void        TakeNote( SCROW nRow, ScPostIt* pNote );
261     /** Returns and forgets a cell note object at the passed row. */
262     ScPostIt*   ReleaseNote( SCROW nRow );
263     /** Deletes the note at the passed row. */
264     void        DeleteNote( SCROW nRow );
265 
266 	void		SetDirty();
267 	void		SetDirty( const ScRange& );
268 	void		SetDirtyVar();
269 	void		SetDirtyAfterLoad();
270 	void		SetTableOpDirty( const ScRange& );
271 	void		CalcAll();
272 	void		CalcAfterLoad();
273 	void		CompileAll();
274 	void		CompileXML( ScProgress& rProgress );
275 
276 	void		ResetChanged( SCROW nStartRow, SCROW nEndRow );
277 
278 	void		UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
279 									 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
280 									 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
281 									 ScDocument* pUndoDoc = NULL );
282 	void		UpdateInsertTab( SCTAB nTable);
283 	void		UpdateInsertTabOnlyCells( SCTAB nTable);
284 	void		UpdateDeleteTab( SCTAB nTable, sal_Bool bIsMove, ScColumn* pRefUndo = NULL );
285 	void		UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo);
286 	void		UpdateCompile( sal_Bool bForceIfNameInUse = sal_False );
287 	void		UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
288 									ScDocument* pUndoDoc );
289 	void		UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
290 
291 	void		SetTabNo(SCTAB nNewTab);
292 	sal_Bool		IsRangeNameInUse(SCROW nRow1, SCROW nRow2, sal_uInt16 nIndex) const;
293     void        FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const;
294 	void 		ReplaceRangeNamesInUse( SCROW nRow1, SCROW nRow2, const ScRangeData::IndexMap& rMap );
295 
296 	const SfxPoolItem*		GetAttr( SCROW nRow, sal_uInt16 nWhich ) const;
297 	const ScPatternAttr*	GetPattern( SCROW nRow ) const;
298     const ScPatternAttr*    GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const;
299 
300 	sal_uLong		GetNumberFormat( SCROW nRow ) const;
301 
302 	void		MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, sal_Bool bDeep ) const;
303 	void		MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, sal_Bool bDeep ) const;
304 	void		MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
305 							ScLineFlags& rFlags,
306 							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight ) const;
307 	void		ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
308 							SCROW nStartRow, SCROW nEndRow, sal_Bool bLeft, SCCOL nDistRight );
309 
310 	void		ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr );
311 	void		ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr );
312 	void		ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr );
313 	void		SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, sal_Bool bPutToPool = sal_False );
314 	void		SetPatternArea( SCROW nStartRow, SCROW nEndRow,
315 								const ScPatternAttr& rPatAttr, sal_Bool bPutToPool = sal_False );
316 	void		ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
317 							const ScPatternAttr& rPattern, short nNewType );
318 
319 	void		ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle );
320 	void		ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle );
321 	void 		ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark);
322 	void		ApplySelectionLineStyle( const ScMarkData& rMark,
323 									const SvxBorderLine* pLine, sal_Bool bColorOnly );
324 
325 	const ScStyleSheet*	GetStyle( SCROW nRow ) const;
326 	const ScStyleSheet*	GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const;
327 	const ScStyleSheet*	GetAreaStyle( sal_Bool& rFound, SCROW nRow1, SCROW nRow2 ) const;
328 
329 	void		FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset );
330 	sal_Bool		IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const;
331 
332                 /// May return -1 if not found
333 	SCsROW		SearchStyle( SCsROW nRow, const ScStyleSheet* pSearchStyle,
334 								sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark );
335 	sal_Bool		SearchStyleRange( SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle,
336 									sal_Bool bUp, sal_Bool bInSelection, const ScMarkData& rMark );
337 
338 	sal_Bool		ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags );
339 	sal_Bool		RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags );
340 	void		ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich );
341 
342 	void		RemoveProtected( SCROW nStartRow, SCROW nEndRow );
343 
344 	SCsROW		ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark );
345     void        DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark );
346 
347 	void		ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
348 	void		ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark );
349 
350 	long		GetNeededSize( SCROW nRow, OutputDevice* pDev,
351 									double nPPTX, double nPPTY,
352 									const Fraction& rZoomX, const Fraction& rZoomY,
353 									sal_Bool bWidth, const ScNeededSizeOptions& rOptions );
354 	sal_uInt16		GetOptimalColWidth( OutputDevice* pDev, double nPPTX, double nPPTY,
355 									const Fraction& rZoomX, const Fraction& rZoomY,
356 									sal_Bool bFormula, sal_uInt16 nOldWidth,
357 									const ScMarkData* pMarkData,
358 									sal_Bool bSimpleTextImport );
359 	void		GetOptimalHeight( SCROW nStartRow, SCROW nEndRow, sal_uInt16* pHeight,
360 									OutputDevice* pDev,
361 									double nPPTX, double nPPTY,
362 									const Fraction& rZoomX, const Fraction& rZoomY,
363 									sal_Bool bShrink, sal_uInt16 nMinHeight, SCROW nMinStart );
364     template< typename TAddLebal, typename TAddData >
365     void        FillDPCacheT( long nDim, SCROW nStartRow, SCROW nEndRow, const TAddLebal & , const TAddData & );
366     void        FillDPCache( ScDPTableDataCache * pCache, long nDim, SCROW nStartRow, SCROW nEndRow );
367 private:
368 	long		GetSimpleTextNeededSize( SCSIZE nIndex, OutputDevice* pDev,
369 									sal_Bool bWidth );
370 public:
371 
372                 /// Including current, may return -1
373 	SCsROW		GetNextUnprotected( SCROW nRow, sal_Bool bUp ) const;
374 
375     void		GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates);
376 	sal_Bool		GetDataEntries(SCROW nRow, TypedScStrCollection& rStrings, sal_Bool bLimit);
377 
378 //UNUSED2008-05  SCROW		NoteCount( SCROW nMaxRow = MAXROW ) const;
379 
380 	void		UpdateInsertTabAbs(SCTAB nNewPos);
381 	sal_Bool		TestTabRefAbs(SCTAB nTable);
382 	sal_Bool 		GetNextSpellingCell(SCROW& nRow, sal_Bool bInSel, const ScMarkData& rData) const;
383 
384 	void		RemoveAutoSpellObj();
385 
386 	void		StartListening( SvtListener& rLst, SCROW nRow );
387 	void		EndListening( SvtListener& rLst, SCROW nRow );
388 	void		MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow );
389 	void		StartAllListeners();
390     void        StartNeededListeners(); // only for cells where NeedsListening()==TRUE
391 	void		SetRelNameDirty();
392 
393 	void 		CompileDBFormula();
394 	void 		CompileDBFormula( sal_Bool bCreateFormulaString );
395 	void 		CompileNameFormula( sal_Bool bCreateFormulaString );
396     void 		CompileColRowNameFormula();
397 
398     sal_Int32	GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const;
399     xub_StrLen  GetMaxNumberStringLen( sal_uInt16& nPrecision,
400                                        SCROW nRowStart, SCROW nRowEnd ) const;
401 
402 private:
403 	ScBaseCell* CloneCell(SCSIZE nIndex, sal_uInt16 nFlags, ScDocument& rDestDoc, const ScAddress& rDestPos);
404 //UNUSED2008-05  void		CorrectSymbolCells( CharSet eStreamCharSet );
405 };
406 
407 
408 class ScColumnIterator					// alle Daten eines Bereichs durchgehen
409 {
410 	const ScColumn*		pColumn;
411 	SCSIZE				nPos;
412 	SCROW				nTop;
413 	SCROW				nBottom;
414 public:
415 				ScColumnIterator( const ScColumn* pCol, SCROW nStart=0, SCROW nEnd=MAXROW );
416 				~ScColumnIterator();
417 
418 	sal_Bool		Next( SCROW& rRow, ScBaseCell*& rpCell );
419 	SCSIZE		GetIndex() const;
420 };
421 
422 
423 class ScMarkedDataIter					// Daten in selektierten Bereichen durchgehen
424 {
425 	const ScColumn*		pColumn;
426 	SCSIZE				nPos;
427 	ScMarkArrayIter*	pMarkIter;
428 	SCROW				nTop;
429 	SCROW				nBottom;
430 	sal_Bool				bNext;
431 	sal_Bool				bAll;
432 
433 public:
434 				ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
435 									sal_Bool bAllIfNone = sal_False );
436 				~ScMarkedDataIter();
437 
438 	sal_Bool		Next( SCSIZE& rIndex );
439 };
440 
441 
442 #endif
443 
444 
445