xref: /trunk/main/sc/source/core/tool/chartpos.cxx (revision 5cd1c82638b65a86a575c9871d07bec79d4064b8)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew 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;
177*5cd1c826Smseidel // TODO:
178cdf0e10cSrcweir /*
179*5cd1c826Smseidel     Erstmal simpel ohne Bitmaskiererei, maximal könnten 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.
182*5cd1c826Smseidel     Weitere Platz-Optimierung wäre, in dem Array nur die wirklich benutzten
183*5cd1c826Smseidel     Zeilen/Spalten abzulegen, würde 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