xref: /aoo41x/main/sc/source/core/tool/chartpos.cxx (revision b3f79822)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b3f79822SAndrew Rist  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19*b3f79822SAndrew Rist  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <tools/table.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "chartpos.hxx"
32cdf0e10cSrcweir #include "document.hxx"
33cdf0e10cSrcweir #include "rechead.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir namespace
36cdf0e10cSrcweir {
lcl_hasValueDataButNoDates(ScDocument * pDocument,SCCOL nCol,SCROW nRow,SCTAB nTab)37cdf0e10cSrcweir     bool lcl_hasValueDataButNoDates( ScDocument* pDocument, SCCOL nCol, SCROW nRow, SCTAB nTab )
38cdf0e10cSrcweir     {
39cdf0e10cSrcweir         bool bReturn = false;
40cdf0e10cSrcweir         if (pDocument->HasValueData( nCol, nRow, nTab ))
41cdf0e10cSrcweir         {
42cdf0e10cSrcweir             //treat dates like text #i25706#
43cdf0e10cSrcweir             sal_uInt32 nNumberFormat = pDocument->GetNumberFormat( ScAddress( nCol, nRow, nTab ) );
44cdf0e10cSrcweir             short nType = pDocument->GetFormatTable()->GetType(nNumberFormat);
45cdf0e10cSrcweir 			bool bIsDate = (nType & NUMBERFORMAT_DATE);
46cdf0e10cSrcweir 			bReturn = !bIsDate;
47cdf0e10cSrcweir         }
48cdf0e10cSrcweir         return bReturn;
49cdf0e10cSrcweir     }
50cdf0e10cSrcweir }
51cdf0e10cSrcweir 
ScChartPositioner(ScDocument * pDoc,SCTAB nTab,SCCOL nStartColP,SCROW nStartRowP,SCCOL nEndColP,SCROW nEndRowP)52cdf0e10cSrcweir ScChartPositioner::ScChartPositioner( ScDocument* pDoc, SCTAB nTab,
53cdf0e10cSrcweir 					SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP) :
54cdf0e10cSrcweir 		pDocument( pDoc ),
55cdf0e10cSrcweir 		pPositionMap( NULL ),
56cdf0e10cSrcweir 		eGlue( SC_CHARTGLUE_NA ),
57cdf0e10cSrcweir 		nStartCol(0),
58cdf0e10cSrcweir 		nStartRow(0),
59cdf0e10cSrcweir 		bColHeaders( sal_False ),
60cdf0e10cSrcweir 		bRowHeaders( sal_False ),
61cdf0e10cSrcweir 		bDummyUpperLeft( sal_False )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir 	SetRangeList( ScRange( nStartColP, nStartRowP, nTab, nEndColP, nEndRowP, nTab ) );
64cdf0e10cSrcweir 	CheckColRowHeaders();
65cdf0e10cSrcweir }
66cdf0e10cSrcweir 
ScChartPositioner(ScDocument * pDoc,const ScRangeListRef & rRangeList)67cdf0e10cSrcweir ScChartPositioner::ScChartPositioner( ScDocument* pDoc, const ScRangeListRef& rRangeList ) :
68cdf0e10cSrcweir 		aRangeListRef( rRangeList ),
69cdf0e10cSrcweir 		pDocument( pDoc ),
70cdf0e10cSrcweir 		pPositionMap( NULL ),
71cdf0e10cSrcweir 		eGlue( SC_CHARTGLUE_NA ),
72cdf0e10cSrcweir 		nStartCol(0),
73cdf0e10cSrcweir 		nStartRow(0),
74cdf0e10cSrcweir 		bColHeaders( sal_False ),
75cdf0e10cSrcweir 		bRowHeaders( sal_False ),
76cdf0e10cSrcweir 		bDummyUpperLeft( sal_False )
77cdf0e10cSrcweir {
78cdf0e10cSrcweir 	if ( aRangeListRef.Is() )
79cdf0e10cSrcweir 		CheckColRowHeaders();
80cdf0e10cSrcweir }
81cdf0e10cSrcweir 
ScChartPositioner(const ScChartPositioner & rPositioner)82cdf0e10cSrcweir ScChartPositioner::ScChartPositioner( const ScChartPositioner& rPositioner ) :
83cdf0e10cSrcweir 		aRangeListRef( rPositioner.aRangeListRef ),
84cdf0e10cSrcweir 		pDocument(rPositioner.pDocument),
85cdf0e10cSrcweir 		pPositionMap( NULL ),
86cdf0e10cSrcweir 		eGlue(rPositioner.eGlue),
87cdf0e10cSrcweir 		nStartCol(rPositioner.nStartCol),
88cdf0e10cSrcweir 		nStartRow(rPositioner.nStartRow),
89cdf0e10cSrcweir 		bColHeaders(rPositioner.bColHeaders),
90cdf0e10cSrcweir 		bRowHeaders(rPositioner.bRowHeaders),
91cdf0e10cSrcweir 		bDummyUpperLeft( rPositioner.bDummyUpperLeft )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
~ScChartPositioner()95cdf0e10cSrcweir ScChartPositioner::~ScChartPositioner()
96cdf0e10cSrcweir {
97cdf0e10cSrcweir 	delete pPositionMap;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
operator ==(const ScChartPositioner & rCmp) const100cdf0e10cSrcweir sal_Bool ScChartPositioner::operator==(const ScChartPositioner& rCmp) const
101cdf0e10cSrcweir {
102cdf0e10cSrcweir 	return bColHeaders == rCmp.bColHeaders
103cdf0e10cSrcweir 		&& bRowHeaders == rCmp.bRowHeaders
104cdf0e10cSrcweir 		&& *aRangeListRef == *rCmp.aRangeListRef;
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
SetRangeList(const ScRange & rRange)107cdf0e10cSrcweir void ScChartPositioner::SetRangeList( const ScRange& rRange )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir 	aRangeListRef = new ScRangeList;
110cdf0e10cSrcweir 	aRangeListRef->Append( rRange );
111cdf0e10cSrcweir 	InvalidateGlue();
112cdf0e10cSrcweir }
113cdf0e10cSrcweir 
GlueState()114cdf0e10cSrcweir void ScChartPositioner::GlueState()
115cdf0e10cSrcweir {
116cdf0e10cSrcweir 	if ( eGlue != SC_CHARTGLUE_NA )
117cdf0e10cSrcweir 		return;
118cdf0e10cSrcweir 	bDummyUpperLeft = sal_False;
119cdf0e10cSrcweir 	ScRangePtr pR;
120cdf0e10cSrcweir 	if ( aRangeListRef->Count() <= 1 )
121cdf0e10cSrcweir 	{
122cdf0e10cSrcweir 		if ( (pR = aRangeListRef->First())!=NULL )
123cdf0e10cSrcweir 		{
124cdf0e10cSrcweir 			if ( pR->aStart.Tab() == pR->aEnd.Tab() )
125cdf0e10cSrcweir 				eGlue = SC_CHARTGLUE_NONE;
126cdf0e10cSrcweir 			else
127cdf0e10cSrcweir 				eGlue = SC_CHARTGLUE_COLS;	// mehrere Tabellen spaltenweise
128cdf0e10cSrcweir 			nStartCol = pR->aStart.Col();
129cdf0e10cSrcweir 			nStartRow = pR->aStart.Row();
130cdf0e10cSrcweir 		}
131cdf0e10cSrcweir 		else
132cdf0e10cSrcweir 		{
133cdf0e10cSrcweir 			InvalidateGlue();
134cdf0e10cSrcweir 			nStartCol = 0;
135cdf0e10cSrcweir 			nStartRow = 0;
136cdf0e10cSrcweir 		}
137cdf0e10cSrcweir 		return;
138cdf0e10cSrcweir 	}
139cdf0e10cSrcweir // 	sal_uLong nOldPos = aRangeListRef->GetCurPos();
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 	pR = aRangeListRef->First();
142cdf0e10cSrcweir 	nStartCol = pR->aStart.Col();
143cdf0e10cSrcweir 	nStartRow = pR->aStart.Row();
144cdf0e10cSrcweir 	SCCOL nMaxCols, nEndCol;
145cdf0e10cSrcweir 	SCROW nMaxRows, nEndRow;
146cdf0e10cSrcweir 	nMaxCols = nEndCol = 0;
147cdf0e10cSrcweir 	nMaxRows = nEndRow = 0;
148cdf0e10cSrcweir 	do
149cdf0e10cSrcweir 	{	// umspannenden Bereich etc. feststellen
150cdf0e10cSrcweir 		SCCOLROW nTmp, n1, n2;
151cdf0e10cSrcweir 		if ( (n1 = pR->aStart.Col()) < nStartCol )
152cdf0e10cSrcweir 			nStartCol = static_cast<SCCOL>(n1);
153cdf0e10cSrcweir 		if ( (n2 = pR->aEnd.Col()) > nEndCol )
154cdf0e10cSrcweir 			nEndCol = static_cast<SCCOL>(n2);
155cdf0e10cSrcweir 		if ( (nTmp = n2 - n1 + 1) > nMaxCols )
156cdf0e10cSrcweir 			nMaxCols = static_cast<SCCOL>(nTmp);
157cdf0e10cSrcweir 		if ( (n1 = pR->aStart.Row()) < nStartRow )
158cdf0e10cSrcweir 			nStartRow = static_cast<SCROW>(n1);
159cdf0e10cSrcweir 		if ( (n2 = pR->aEnd.Row()) > nEndRow )
160cdf0e10cSrcweir 			nEndRow = static_cast<SCROW>(n2);
161cdf0e10cSrcweir 		if ( (nTmp = n2 - n1 + 1) > nMaxRows )
162cdf0e10cSrcweir 			nMaxRows = static_cast<SCROW>(nTmp);
163cdf0e10cSrcweir 	} while ( (pR = aRangeListRef->Next())!=NULL );
164cdf0e10cSrcweir 	SCCOL nC = nEndCol - nStartCol + 1;
165cdf0e10cSrcweir 	if ( nC == 1 )
166cdf0e10cSrcweir 	{
167cdf0e10cSrcweir 		eGlue = SC_CHARTGLUE_ROWS;
168cdf0e10cSrcweir 		return;
169cdf0e10cSrcweir 	}
170cdf0e10cSrcweir 	SCROW nR = nEndRow - nStartRow + 1;
171cdf0e10cSrcweir 	if ( nR == 1 )
172cdf0e10cSrcweir 	{
173cdf0e10cSrcweir 		eGlue = SC_CHARTGLUE_COLS;
174cdf0e10cSrcweir 		return;
175cdf0e10cSrcweir 	}
176cdf0e10cSrcweir 	sal_uLong nCR = (sal_uLong)nC * nR;
177cdf0e10cSrcweir //2do:
178cdf0e10cSrcweir /*
179cdf0e10cSrcweir 	Erstmal simpel ohne Bitmaskiererei, maximal koennten so 8MB alloziert
180cdf0e10cSrcweir 	werden (256 Cols mal 32000 Rows), das liesse sich mit 2 Bit je Eintrag
181cdf0e10cSrcweir 	auf 2MB reduzieren, andererseits ist es so schneller.
182cdf0e10cSrcweir 	Weitere Platz-Optimierung waere, in dem Array nur die wirklich benutzten
183cdf0e10cSrcweir 	Zeilen/Spalten abzulegen, wuerde aber ein weiteres durchlaufen der
184cdf0e10cSrcweir 	RangeList und indirekten Zugriff auf das Array bedeuten.
185cdf0e10cSrcweir  */
186cdf0e10cSrcweir 	const sal_uInt8 nHole = 0;
187cdf0e10cSrcweir 	const sal_uInt8 nOccu = 1;
188cdf0e10cSrcweir 	const sal_uInt8 nFree = 2;
189cdf0e10cSrcweir 	const sal_uInt8 nGlue = 3;
190cdf0e10cSrcweir 	sal_uInt8* p;
191cdf0e10cSrcweir 	sal_uInt8* pA = new sal_uInt8[ nCR ];
192cdf0e10cSrcweir 	memset( pA, 0, nCR * sizeof(sal_uInt8) );
193cdf0e10cSrcweir 
194cdf0e10cSrcweir 	SCCOL nCol, nCol1, nCol2;
195cdf0e10cSrcweir 	SCROW nRow, nRow1, nRow2;
196cdf0e10cSrcweir 	for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() )
197cdf0e10cSrcweir 	{	// Selektionen 2D als belegt markieren
198cdf0e10cSrcweir 		nCol1 = pR->aStart.Col() - nStartCol;
199cdf0e10cSrcweir 		nCol2 = pR->aEnd.Col() - nStartCol;
200cdf0e10cSrcweir 		nRow1 = pR->aStart.Row() - nStartRow;
201cdf0e10cSrcweir 		nRow2 = pR->aEnd.Row() - nStartRow;
202cdf0e10cSrcweir 		for ( nCol = nCol1; nCol <= nCol2; nCol++ )
203cdf0e10cSrcweir 		{
204cdf0e10cSrcweir 			p = pA + (sal_uLong)nCol * nR + nRow1;
205cdf0e10cSrcweir 			for ( nRow = nRow1; nRow <= nRow2; nRow++, p++ )
206cdf0e10cSrcweir 				*p = nOccu;
207cdf0e10cSrcweir 		}
208cdf0e10cSrcweir 	}
209cdf0e10cSrcweir 	sal_Bool bGlue = sal_True;
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 	sal_Bool bGlueCols = sal_False;
212cdf0e10cSrcweir 	for ( nCol = 0; bGlue && nCol < nC; nCol++ )
213cdf0e10cSrcweir 	{	// Spalten probieren durchzugehen und als frei markieren
214cdf0e10cSrcweir 		p = pA + (sal_uLong)nCol * nR;
215cdf0e10cSrcweir 		for ( nRow = 0; bGlue && nRow < nR; nRow++, p++ )
216cdf0e10cSrcweir 		{
217cdf0e10cSrcweir 			if ( *p == nOccu )
218cdf0e10cSrcweir 			{	// Wenn einer mittendrin liegt ist keine Zusammenfassung
219cdf0e10cSrcweir 				// moeglich. Am Rand koennte ok sein, wenn in dieser Spalte
220cdf0e10cSrcweir 				// in jeder belegten Zeile einer belegt ist.
221cdf0e10cSrcweir 				if ( nRow > 0 && nCol > 0 )
222cdf0e10cSrcweir 					bGlue = sal_False;		// nCol==0 kann DummyUpperLeft sein
223cdf0e10cSrcweir 				else
224cdf0e10cSrcweir 					nRow = nR;
225cdf0e10cSrcweir 			}
226cdf0e10cSrcweir 			else
227cdf0e10cSrcweir 				*p = nFree;
228cdf0e10cSrcweir 		}
229cdf0e10cSrcweir 		if ( bGlue && *(p = (pA + ((((sal_uLong)nCol+1) * nR) - 1))) == nFree )
230cdf0e10cSrcweir 		{	// Spalte als komplett frei markieren
231cdf0e10cSrcweir 			*p = nGlue;
232cdf0e10cSrcweir 			bGlueCols = sal_True;		// mindestens eine freie Spalte
233cdf0e10cSrcweir 		}
234cdf0e10cSrcweir 	}
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 	sal_Bool bGlueRows = sal_False;
237cdf0e10cSrcweir 	for ( nRow = 0; bGlue && nRow < nR; nRow++ )
238cdf0e10cSrcweir 	{	// Zeilen probieren durchzugehen und als frei markieren
239cdf0e10cSrcweir 		p = pA + nRow;
240cdf0e10cSrcweir 		for ( nCol = 0; bGlue && nCol < nC; nCol++, p+=nR )
241cdf0e10cSrcweir 		{
242cdf0e10cSrcweir 			if ( *p == nOccu )
243cdf0e10cSrcweir 			{
244cdf0e10cSrcweir 				if ( nCol > 0 && nRow > 0 )
245cdf0e10cSrcweir 					bGlue = sal_False;		// nRow==0 kann DummyUpperLeft sein
246cdf0e10cSrcweir 				else
247cdf0e10cSrcweir 					nCol = nC;
248cdf0e10cSrcweir 			}
249cdf0e10cSrcweir 			else
250cdf0e10cSrcweir 				*p = nFree;
251cdf0e10cSrcweir 		}
252cdf0e10cSrcweir 		if ( bGlue && *(p = (pA + ((((sal_uLong)nC-1) * nR) + nRow))) == nFree )
253cdf0e10cSrcweir 		{	// Zeile als komplett frei markieren
254cdf0e10cSrcweir 			*p = nGlue;
255cdf0e10cSrcweir 			bGlueRows = sal_True;		// mindestens eine freie Zeile
256cdf0e10cSrcweir 		}
257cdf0e10cSrcweir 	}
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	// n=1: die linke obere Ecke koennte bei Beschriftung automagisch
260cdf0e10cSrcweir 	// hinzugezogen werden
261cdf0e10cSrcweir 	p = pA + 1;
262cdf0e10cSrcweir 	for ( sal_uLong n = 1; bGlue && n < nCR; n++, p++ )
263cdf0e10cSrcweir 	{	// ein unberuehrtes Feld heisst, dass es weder spaltenweise noch
264cdf0e10cSrcweir 		// zeilenweise zu erreichen war, also nichts zusamenzufassen
265cdf0e10cSrcweir 		if ( *p == nHole )
266cdf0e10cSrcweir 			bGlue = sal_False;
267cdf0e10cSrcweir 	}
268cdf0e10cSrcweir 	if ( bGlue )
269cdf0e10cSrcweir 	{
270cdf0e10cSrcweir 		if ( bGlueCols && bGlueRows )
271cdf0e10cSrcweir 			eGlue = SC_CHARTGLUE_BOTH;
272cdf0e10cSrcweir 		else if ( bGlueRows )
273cdf0e10cSrcweir 			eGlue = SC_CHARTGLUE_ROWS;
274cdf0e10cSrcweir 		else
275cdf0e10cSrcweir 			eGlue = SC_CHARTGLUE_COLS;
276cdf0e10cSrcweir 		if ( *pA != nOccu )
277cdf0e10cSrcweir 			bDummyUpperLeft = sal_True;
278cdf0e10cSrcweir 	}
279cdf0e10cSrcweir 	else
280cdf0e10cSrcweir 	{
281cdf0e10cSrcweir 		eGlue = SC_CHARTGLUE_NONE;
282cdf0e10cSrcweir 	}
283cdf0e10cSrcweir 
284cdf0e10cSrcweir 	delete [] pA;
285cdf0e10cSrcweir }
286cdf0e10cSrcweir 
CheckColRowHeaders()287cdf0e10cSrcweir void ScChartPositioner::CheckColRowHeaders()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir 	SCCOL nCol1, nCol2, iCol;
290cdf0e10cSrcweir 	SCROW nRow1, nRow2, iRow;
291cdf0e10cSrcweir 	SCTAB nTab1, nTab2;
292cdf0e10cSrcweir 
293cdf0e10cSrcweir 	sal_Bool bColStrings = sal_True;
294cdf0e10cSrcweir 	sal_Bool bRowStrings = sal_True;
295cdf0e10cSrcweir 	GlueState();
296cdf0e10cSrcweir 	if ( aRangeListRef->Count() == 1 )
297cdf0e10cSrcweir 	{
298cdf0e10cSrcweir 		aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
299cdf0e10cSrcweir 		if ( nCol1 > nCol2 || nRow1 > nRow2 )
300cdf0e10cSrcweir 			bColStrings = bRowStrings = sal_False;
301cdf0e10cSrcweir 		else
302cdf0e10cSrcweir 		{
303cdf0e10cSrcweir 			for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++)
304cdf0e10cSrcweir 			{
305cdf0e10cSrcweir 				if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 ))
306cdf0e10cSrcweir 						bColStrings = sal_False;
307cdf0e10cSrcweir 			}
308cdf0e10cSrcweir 			for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++)
309cdf0e10cSrcweir 			{
310cdf0e10cSrcweir 				if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 ))
311cdf0e10cSrcweir 						bRowStrings = sal_False;
312cdf0e10cSrcweir 			}
313cdf0e10cSrcweir 		}
314cdf0e10cSrcweir 	}
315cdf0e10cSrcweir 	else
316cdf0e10cSrcweir 	{
317cdf0e10cSrcweir 		sal_Bool bVert = (eGlue == SC_CHARTGLUE_NONE || eGlue == SC_CHARTGLUE_ROWS);
318cdf0e10cSrcweir 		for ( ScRangePtr pR = aRangeListRef->First();
319cdf0e10cSrcweir 				pR && (bColStrings || bRowStrings);
320cdf0e10cSrcweir 				pR = aRangeListRef->Next() )
321cdf0e10cSrcweir 		{
322cdf0e10cSrcweir 			pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
323cdf0e10cSrcweir 			sal_Bool bTopRow = (nRow1 == nStartRow);
324cdf0e10cSrcweir 			if ( bRowStrings && (bVert || nCol1 == nStartCol) )
325cdf0e10cSrcweir 			{	// NONE oder ROWS: RowStrings in jeder Selektion moeglich
326cdf0e10cSrcweir 				// COLS oder BOTH: nur aus der ersten Spalte
327cdf0e10cSrcweir 				if ( nCol1 <= nCol2 )
328cdf0e10cSrcweir 					for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++)
329cdf0e10cSrcweir 					{
330cdf0e10cSrcweir 						if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 ))
331cdf0e10cSrcweir 								bRowStrings = sal_False;
332cdf0e10cSrcweir 					}
333cdf0e10cSrcweir 			}
334cdf0e10cSrcweir 			if ( bColStrings && bTopRow )
335cdf0e10cSrcweir 			{	// ColStrings nur aus der ersten Zeile
336cdf0e10cSrcweir 				if ( nRow1 <= nRow2 )
337cdf0e10cSrcweir 					for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++)
338cdf0e10cSrcweir 					{
339cdf0e10cSrcweir 						if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 ))
340cdf0e10cSrcweir 								bColStrings = sal_False;
341cdf0e10cSrcweir 					}
342cdf0e10cSrcweir 			}
343cdf0e10cSrcweir 		}
344cdf0e10cSrcweir 	}
345cdf0e10cSrcweir 	bColHeaders = bColStrings;
346cdf0e10cSrcweir 	bRowHeaders = bRowStrings;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
GetPositionMap()349cdf0e10cSrcweir const ScChartPositionMap* ScChartPositioner::GetPositionMap()
350cdf0e10cSrcweir {
351cdf0e10cSrcweir     CreatePositionMap();
352cdf0e10cSrcweir 	return pPositionMap;
353cdf0e10cSrcweir }
354cdf0e10cSrcweir 
355cdf0e10cSrcweir 
CreatePositionMap()356cdf0e10cSrcweir void ScChartPositioner::CreatePositionMap()
357cdf0e10cSrcweir {
358cdf0e10cSrcweir 	if ( eGlue == SC_CHARTGLUE_NA && pPositionMap )
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		delete pPositionMap;
361cdf0e10cSrcweir 		pPositionMap = NULL;
362cdf0e10cSrcweir 	}
363cdf0e10cSrcweir 
364cdf0e10cSrcweir 	if ( pPositionMap )
365cdf0e10cSrcweir 		return ;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir 	SCSIZE nColAdd = bRowHeaders ? 1 : 0;
368cdf0e10cSrcweir 	SCSIZE nRowAdd = bColHeaders ? 1 : 0;
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 	SCCOL nCol, nCol1, nCol2;
371cdf0e10cSrcweir 	SCROW nRow, nRow1, nRow2;
372cdf0e10cSrcweir 	SCTAB nTab, nTab1, nTab2;
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 	//
375cdf0e10cSrcweir 	//	wirkliche Groesse (ohne versteckte Zeilen/Spalten)
376cdf0e10cSrcweir 	//
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 	SCSIZE nColCount = 0;
379cdf0e10cSrcweir     SCSIZE nRowCount = 0;
380cdf0e10cSrcweir 
381cdf0e10cSrcweir 	GlueState();
382cdf0e10cSrcweir 
383cdf0e10cSrcweir 	sal_Bool bNoGlue = (eGlue == SC_CHARTGLUE_NONE);
384cdf0e10cSrcweir 	Table* pCols = new Table;
385cdf0e10cSrcweir 	Table* pNewRowTable = new Table;
386cdf0e10cSrcweir 	ScAddress* pNewAddress = new ScAddress;
387cdf0e10cSrcweir 	ScRangePtr pR;
388cdf0e10cSrcweir 	Table* pCol;
389cdf0e10cSrcweir 	ScAddress* pPos;
390cdf0e10cSrcweir 	SCROW nNoGlueRow = 0;
391cdf0e10cSrcweir 	for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() )
392cdf0e10cSrcweir 	{
393cdf0e10cSrcweir 		pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
394cdf0e10cSrcweir 		for ( nTab = nTab1; nTab <= nTab2; nTab++ )
395cdf0e10cSrcweir 		{
396cdf0e10cSrcweir 			// nTab im ColKey, um gleiche Col/Row in anderer Table haben zu koennen
397cdf0e10cSrcweir             sal_uLong nInsCol = (static_cast<sal_uLong>(nTab) << 16) | (bNoGlue ? 0 :
398cdf0e10cSrcweir                     static_cast<sal_uLong>(nCol1));
399cdf0e10cSrcweir 			for ( nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol )
400cdf0e10cSrcweir 			{
401cdf0e10cSrcweir 				if ( bNoGlue || eGlue == SC_CHARTGLUE_ROWS )
402cdf0e10cSrcweir 				{	// meistens gleiche Cols
403cdf0e10cSrcweir 					if ( (pCol = (Table*) pCols->Get( nInsCol ))==NULL )
404cdf0e10cSrcweir 					{
405cdf0e10cSrcweir 						pCols->Insert( nInsCol, pNewRowTable );
406cdf0e10cSrcweir 						pCol = pNewRowTable;
407cdf0e10cSrcweir 						pNewRowTable = new Table;
408cdf0e10cSrcweir 					}
409cdf0e10cSrcweir 				}
410cdf0e10cSrcweir 				else
411cdf0e10cSrcweir 				{	// meistens neue Cols
412cdf0e10cSrcweir 					if ( pCols->Insert( nInsCol, pNewRowTable ) )
413cdf0e10cSrcweir 					{
414cdf0e10cSrcweir 						pCol = pNewRowTable;
415cdf0e10cSrcweir 						pNewRowTable = new Table;
416cdf0e10cSrcweir 					}
417cdf0e10cSrcweir 					else
418cdf0e10cSrcweir 						pCol = (Table*) pCols->Get( nInsCol );
419cdf0e10cSrcweir 				}
420cdf0e10cSrcweir 				// bei anderer Tabelle wurde bereits neuer ColKey erzeugt,
421cdf0e10cSrcweir 				// die Zeilen muessen fuer's Dummy fuellen gleich sein!
422cdf0e10cSrcweir 				sal_uLong nInsRow = (bNoGlue ? nNoGlueRow : nRow1);
423cdf0e10cSrcweir 				for ( nRow = nRow1; nRow <= nRow2; nRow++, nInsRow++ )
424cdf0e10cSrcweir 				{
425cdf0e10cSrcweir 					if ( pCol->Insert( nInsRow, pNewAddress ) )
426cdf0e10cSrcweir 					{
427cdf0e10cSrcweir 						pNewAddress->Set( nCol, nRow, nTab );
428cdf0e10cSrcweir 						pNewAddress = new ScAddress;
429cdf0e10cSrcweir 					}
430cdf0e10cSrcweir 				}
431cdf0e10cSrcweir 			}
432cdf0e10cSrcweir 		}
433cdf0e10cSrcweir 		// bei NoGlue werden zusammengehoerige Tabellen als ColGlue dargestellt
434cdf0e10cSrcweir 		nNoGlueRow += nRow2 - nRow1 + 1;
435cdf0e10cSrcweir 	}
436cdf0e10cSrcweir 	delete pNewAddress;
437cdf0e10cSrcweir 	delete pNewRowTable;
438cdf0e10cSrcweir 
439cdf0e10cSrcweir 	// Anzahl der Daten
440cdf0e10cSrcweir 	nColCount = static_cast< SCSIZE >( pCols->Count());
441cdf0e10cSrcweir 	if ( (pCol = (Table*) pCols->First())!=NULL )
442cdf0e10cSrcweir 	{
443cdf0e10cSrcweir 		if ( bDummyUpperLeft )
444cdf0e10cSrcweir 			pCol->Insert( 0, (void*)0 );		// Dummy fuer Beschriftung
445cdf0e10cSrcweir 		nRowCount = static_cast< SCSIZE >( pCol->Count());
446cdf0e10cSrcweir 	}
447cdf0e10cSrcweir 	else
448cdf0e10cSrcweir 		nRowCount = 0;
449cdf0e10cSrcweir 	if ( nColCount > 0 )
450cdf0e10cSrcweir 		nColCount -= nColAdd;
451cdf0e10cSrcweir 	if ( nRowCount > 0 )
452cdf0e10cSrcweir 		nRowCount -= nRowAdd;
453cdf0e10cSrcweir 
454cdf0e10cSrcweir 	if ( nColCount==0 || nRowCount==0 )
455cdf0e10cSrcweir 	{	// einen Eintrag ohne Daten erzeugen
456cdf0e10cSrcweir 		pR = aRangeListRef->First();
457cdf0e10cSrcweir 		if ( pCols->Count() > 0 )
458cdf0e10cSrcweir 			pCol = (Table*) pCols->First();
459cdf0e10cSrcweir 		else
460cdf0e10cSrcweir 		{
461cdf0e10cSrcweir 			pCol = new Table;
462cdf0e10cSrcweir 			pCols->Insert( 0, pCol );
463cdf0e10cSrcweir 		}
464cdf0e10cSrcweir 		nColCount = 1;
465cdf0e10cSrcweir 		if ( pCol->Count() > 0 )
466cdf0e10cSrcweir 		{	// kann ja eigentlich nicht sein, wenn nColCount==0 || nRowCount==0
467cdf0e10cSrcweir 			pPos = (ScAddress*) pCol->First();
468cdf0e10cSrcweir 			if ( pPos )
469cdf0e10cSrcweir 			{
470cdf0e10cSrcweir 				delete pPos;
471cdf0e10cSrcweir 				pCol->Replace( pCol->GetCurKey(), (void*)0 );
472cdf0e10cSrcweir 			}
473cdf0e10cSrcweir 		}
474cdf0e10cSrcweir 		else
475cdf0e10cSrcweir 			pCol->Insert( 0, (void*)0 );
476cdf0e10cSrcweir 		nRowCount = 1;
477cdf0e10cSrcweir 		nColAdd = 0;
478cdf0e10cSrcweir 		nRowAdd = 0;
479cdf0e10cSrcweir 	}
480cdf0e10cSrcweir 	else
481cdf0e10cSrcweir 	{
482cdf0e10cSrcweir 		if ( bNoGlue )
483cdf0e10cSrcweir 		{	// Luecken mit Dummies fuellen, erste Spalte ist Master
484cdf0e10cSrcweir 			Table* pFirstCol = (Table*) pCols->First();
485cdf0e10cSrcweir 			sal_uLong nCount = pFirstCol->Count();
486cdf0e10cSrcweir 			pFirstCol->First();
487cdf0e10cSrcweir 			for ( sal_uLong n = 0; n < nCount; n++, pFirstCol->Next() )
488cdf0e10cSrcweir 			{
489cdf0e10cSrcweir 				sal_uLong nKey = pFirstCol->GetCurKey();
490cdf0e10cSrcweir 				pCols->First();
491cdf0e10cSrcweir 				while ( (pCol = (Table*) pCols->Next())!=NULL )
492cdf0e10cSrcweir 					pCol->Insert( nKey, (void*)0 );		// keine Daten
493cdf0e10cSrcweir 			}
494cdf0e10cSrcweir 		}
495cdf0e10cSrcweir 	}
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 	pPositionMap = new ScChartPositionMap( static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount),
498cdf0e10cSrcweir 		static_cast<SCCOL>(nColAdd), static_cast<SCROW>(nRowAdd), *pCols );
499cdf0e10cSrcweir 
500cdf0e10cSrcweir 	//	Aufraeumen
501cdf0e10cSrcweir 	for ( pCol = (Table*) pCols->First(); pCol; pCol = (Table*) pCols->Next() )
502cdf0e10cSrcweir 	{	//! nur Tables loeschen, nicht die ScAddress*
503cdf0e10cSrcweir 		delete pCol;
504cdf0e10cSrcweir 	}
505cdf0e10cSrcweir 	delete pCols;
506cdf0e10cSrcweir }
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 
ScChartPositionMap(SCCOL nChartCols,SCROW nChartRows,SCCOL nColAdd,SCROW nRowAdd,Table & rCols)509cdf0e10cSrcweir ScChartPositionMap::ScChartPositionMap( SCCOL nChartCols, SCROW nChartRows,
510cdf0e10cSrcweir 			SCCOL nColAdd, SCROW nRowAdd, Table& rCols ) :
511cdf0e10cSrcweir 		ppData( new ScAddress* [ nChartCols * nChartRows ] ),
512cdf0e10cSrcweir 		ppColHeader( new ScAddress* [ nChartCols ] ),
513cdf0e10cSrcweir 		ppRowHeader( new ScAddress* [ nChartRows ] ),
514cdf0e10cSrcweir 		nCount( (sal_uLong) nChartCols * nChartRows ),
515cdf0e10cSrcweir 		nColCount( nChartCols ),
516cdf0e10cSrcweir 		nRowCount( nChartRows )
517cdf0e10cSrcweir {
518cdf0e10cSrcweir 	DBG_ASSERT( nColCount && nRowCount, "ScChartPositionMap without dimension" );
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 	ScAddress* pPos;
521cdf0e10cSrcweir 	SCCOL nCol;
522cdf0e10cSrcweir 	SCROW nRow;
523cdf0e10cSrcweir 
524cdf0e10cSrcweir 	Table* pCol = (Table*) rCols.First();
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 	// Zeilen-Header
527cdf0e10cSrcweir 	pPos = (ScAddress*) pCol->First();
528cdf0e10cSrcweir 	if ( nRowAdd )
529cdf0e10cSrcweir 		pPos = (ScAddress*) pCol->Next();
530cdf0e10cSrcweir 	if ( nColAdd )
531cdf0e10cSrcweir 	{	// eigenstaendig
532cdf0e10cSrcweir 		for ( nRow = 0; nRow < nRowCount; nRow++ )
533cdf0e10cSrcweir 		{
534cdf0e10cSrcweir 			ppRowHeader[ nRow ] = pPos;
535cdf0e10cSrcweir 			pPos = (ScAddress*) pCol->Next();
536cdf0e10cSrcweir 		}
537cdf0e10cSrcweir 	}
538cdf0e10cSrcweir 	else
539cdf0e10cSrcweir 	{	// Kopie
540cdf0e10cSrcweir 		for ( nRow = 0; nRow < nRowCount; nRow++ )
541cdf0e10cSrcweir 		{
542cdf0e10cSrcweir 			ppRowHeader[ nRow ] = ( pPos ? new ScAddress( *pPos ) : NULL );
543cdf0e10cSrcweir 			pPos = (ScAddress*) pCol->Next();
544cdf0e10cSrcweir 		}
545cdf0e10cSrcweir 	}
546cdf0e10cSrcweir 	if ( nColAdd )
547cdf0e10cSrcweir 		pCol = (Table*) rCols.Next();
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 	// Daten spaltenweise und Spalten-Header
550cdf0e10cSrcweir 	sal_uLong nIndex = 0;
551cdf0e10cSrcweir 	for ( nCol = 0; nCol < nColCount; nCol++ )
552cdf0e10cSrcweir 	{
553cdf0e10cSrcweir 		if ( pCol )
554cdf0e10cSrcweir 		{
555cdf0e10cSrcweir 			pPos = (ScAddress*) pCol->First();
556cdf0e10cSrcweir 			if ( nRowAdd )
557cdf0e10cSrcweir 			{
558cdf0e10cSrcweir 				ppColHeader[ nCol ] = pPos;		// eigenstaendig
559cdf0e10cSrcweir 				pPos = (ScAddress*) pCol->Next();
560cdf0e10cSrcweir 			}
561cdf0e10cSrcweir 			else
562cdf0e10cSrcweir 				ppColHeader[ nCol ] = ( pPos ? new ScAddress( *pPos ) : NULL );
563cdf0e10cSrcweir 			for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
564cdf0e10cSrcweir 			{
565cdf0e10cSrcweir 				ppData[ nIndex ] = pPos;
566cdf0e10cSrcweir 				pPos = (ScAddress*) pCol->Next();
567cdf0e10cSrcweir 			}
568cdf0e10cSrcweir 		}
569cdf0e10cSrcweir 		else
570cdf0e10cSrcweir 		{
571cdf0e10cSrcweir 			ppColHeader[ nCol ] = NULL;
572cdf0e10cSrcweir 			for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
573cdf0e10cSrcweir 			{
574cdf0e10cSrcweir 				ppData[ nIndex ] = NULL;
575cdf0e10cSrcweir 			}
576cdf0e10cSrcweir 		}
577cdf0e10cSrcweir 		pCol = (Table*) rCols.Next();
578cdf0e10cSrcweir 	}
579cdf0e10cSrcweir }
580cdf0e10cSrcweir 
581cdf0e10cSrcweir 
~ScChartPositionMap()582cdf0e10cSrcweir ScChartPositionMap::~ScChartPositionMap()
583cdf0e10cSrcweir {
584cdf0e10cSrcweir 	for ( sal_uLong nIndex=0; nIndex < nCount; nIndex++ )
585cdf0e10cSrcweir 	{
586cdf0e10cSrcweir 		delete ppData[nIndex];
587cdf0e10cSrcweir 	}
588cdf0e10cSrcweir 	delete [] ppData;
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 	SCCOL j;
591cdf0e10cSrcweir 	for ( j=0; j < nColCount; j++ )
592cdf0e10cSrcweir 	{
593cdf0e10cSrcweir 		delete ppColHeader[j];
594cdf0e10cSrcweir 	}
595cdf0e10cSrcweir 	delete [] ppColHeader;
596cdf0e10cSrcweir 	SCROW i;
597cdf0e10cSrcweir 	for ( i=0; i < nRowCount; i++ )
598cdf0e10cSrcweir 	{
599cdf0e10cSrcweir 		delete ppRowHeader[i];
600cdf0e10cSrcweir 	}
601cdf0e10cSrcweir 	delete [] ppRowHeader;
602cdf0e10cSrcweir }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 
605cdf0e10cSrcweir //UNUSED2009-05 ScRangeListRef ScChartPositionMap::GetColRanges( SCCOL nChartCol ) const
606cdf0e10cSrcweir //UNUSED2009-05 {
607cdf0e10cSrcweir //UNUSED2009-05     ScRangeListRef xRangeList = new ScRangeList;
608cdf0e10cSrcweir //UNUSED2009-05     if ( nChartCol < nColCount )
609cdf0e10cSrcweir //UNUSED2009-05     {
610cdf0e10cSrcweir //UNUSED2009-05         sal_uLong nStop = GetIndex( nChartCol, nRowCount );
611cdf0e10cSrcweir //UNUSED2009-05         for ( sal_uLong nIndex = GetIndex( nChartCol, 0 ); nIndex < nStop; nIndex++ )
612cdf0e10cSrcweir //UNUSED2009-05         {
613cdf0e10cSrcweir //UNUSED2009-05             if ( ppData[ nIndex ] )
614cdf0e10cSrcweir //UNUSED2009-05                 xRangeList->Join( *ppData[ nIndex ] );
615cdf0e10cSrcweir //UNUSED2009-05         }
616cdf0e10cSrcweir //UNUSED2009-05     }
617cdf0e10cSrcweir //UNUSED2009-05     return xRangeList;
618cdf0e10cSrcweir //UNUSED2009-05 }
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 
621cdf0e10cSrcweir //UNUSED2009-05 ScRangeListRef ScChartPositionMap::GetRowRanges( SCROW nChartRow ) const
622cdf0e10cSrcweir //UNUSED2009-05 {
623cdf0e10cSrcweir //UNUSED2009-05     ScRangeListRef xRangeList = new ScRangeList;
624cdf0e10cSrcweir //UNUSED2009-05     if ( nChartRow < nRowCount )
625cdf0e10cSrcweir //UNUSED2009-05     {
626cdf0e10cSrcweir //UNUSED2009-05         sal_uLong nStop = GetIndex( nColCount, nChartRow );
627cdf0e10cSrcweir //UNUSED2009-05         for ( sal_uLong nIndex = GetIndex( 0, nChartRow ); nIndex < nStop;
628cdf0e10cSrcweir //UNUSED2009-05                 nIndex += nRowCount )
629cdf0e10cSrcweir //UNUSED2009-05         {
630cdf0e10cSrcweir //UNUSED2009-05             if ( ppData[ nIndex ] )
631cdf0e10cSrcweir //UNUSED2009-05                 xRangeList->Join( *ppData[ nIndex ] );
632cdf0e10cSrcweir //UNUSED2009-05         }
633cdf0e10cSrcweir //UNUSED2009-05     }
634cdf0e10cSrcweir //UNUSED2009-05     return xRangeList;
635cdf0e10cSrcweir //UNUSED2009-05 }
636