xref: /AOO41X/main/sc/source/ui/pagedlg/areasdlg.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 //----------------------------------------------------------------------------
30 #include <rangelst.hxx>
31 
32 #include <sfx2/dispatch.hxx>
33 #include <svl/stritem.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <unotools/charclass.hxx>
36 #include <stdlib.h>
37 
38 #define _AREASDLG_CXX
39 #include "areasdlg.hxx"
40 #undef _AREASDLG_CXX
41 
42 #include "scresid.hxx"
43 #include "rangenam.hxx"
44 #include "reffact.hxx"
45 #include "tabvwsh.hxx"
46 #include "docsh.hxx"
47 #include "globstr.hrc"
48 #include "pagedlg.hrc"
49 #include "compiler.hxx"
50 
51 // STATIC DATA ---------------------------------------------------------------
52 
53 // List box positions for print range (PR)
54 const sal_uInt16 SC_AREASDLG_PR_NONE    = 0;
55 const sal_uInt16 SC_AREASDLG_PR_ENTIRE  = 1;
56 const sal_uInt16 SC_AREASDLG_PR_USER    = 2;
57 const sal_uInt16 SC_AREASDLG_PR_SELECT  = 3;
58 const sal_uInt16 SC_AREASDLG_PR_OFFSET  = 4;
59 
60 // List box positions for repeat ranges (RR)
61 const sal_uInt16 SC_AREASDLG_RR_NONE    = 0;
62 const sal_uInt16 SC_AREASDLG_RR_USER    = 1;
63 const sal_uInt16 SC_AREASDLG_RR_OFFSET  = 2;
64 
65 //============================================================================
66 
67 #define HDL(hdl)            LINK( this, ScPrintAreasDlg, hdl )
68 #define ERRORBOX(nId)       ErrorBox( this, WinBits(WB_OK|WB_DEF_OK), \
69                             ScGlobal::GetRscString( nId ) ).Execute()
70 #define SWAP(x1,x2)         { int n=x1; x1=x2; x2=n; }
71 
72 // globale Funktionen (->am Ende der Datei):
73 
74 bool    lcl_CheckRepeatString( const String& rStr, ScDocument* pDoc, bool bIsRow, ScRange* pRange );
75 void    lcl_GetRepeatRangeString( const ScRange* pRange, ScDocument* pDoc, bool bIsRow, String& rStr );
76 
77 #if 0
78 static void printAddressFlags(sal_uInt16 nFlag)
79 {
80     if ((nFlag & SCA_COL_ABSOLUTE  ) == SCA_COL_ABSOLUTE  )  printf("SCA_COL_ABSOLUTE \n");
81     if ((nFlag & SCA_ROW_ABSOLUTE  ) == SCA_ROW_ABSOLUTE  )  printf("SCA_ROW_ABSOLUTE \n");
82     if ((nFlag & SCA_TAB_ABSOLUTE  ) == SCA_TAB_ABSOLUTE  )  printf("SCA_TAB_ABSOLUTE \n");
83     if ((nFlag & SCA_TAB_3D        ) == SCA_TAB_3D        )  printf("SCA_TAB_3D       \n");
84     if ((nFlag & SCA_COL2_ABSOLUTE ) == SCA_COL2_ABSOLUTE )  printf("SCA_COL2_ABSOLUTE\n");
85     if ((nFlag & SCA_ROW2_ABSOLUTE ) == SCA_ROW2_ABSOLUTE )  printf("SCA_ROW2_ABSOLUTE\n");
86     if ((nFlag & SCA_TAB2_ABSOLUTE ) == SCA_TAB2_ABSOLUTE )  printf("SCA_TAB2_ABSOLUTE\n");
87     if ((nFlag & SCA_TAB2_3D       ) == SCA_TAB2_3D       )  printf("SCA_TAB2_3D      \n");
88     if ((nFlag & SCA_VALID_ROW     ) == SCA_VALID_ROW     )  printf("SCA_VALID_ROW    \n");
89     if ((nFlag & SCA_VALID_COL     ) == SCA_VALID_COL     )  printf("SCA_VALID_COL    \n");
90     if ((nFlag & SCA_VALID_TAB     ) == SCA_VALID_TAB     )  printf("SCA_VALID_TAB    \n");
91     if ((nFlag & SCA_FORCE_DOC     ) == SCA_FORCE_DOC     )  printf("SCA_FORCE_DOC    \n");
92     if ((nFlag & SCA_VALID_ROW2    ) == SCA_VALID_ROW2    )  printf("SCA_VALID_ROW2   \n");
93     if ((nFlag & SCA_VALID_COL2    ) == SCA_VALID_COL2    )  printf("SCA_VALID_COL2   \n");
94     if ((nFlag & SCA_VALID_TAB2    ) == SCA_VALID_TAB2    )  printf("SCA_VALID_TAB2   \n");
95     if ((nFlag & SCA_VALID         ) == SCA_VALID         )  printf("SCA_VALID        \n");
96     if ((nFlag & SCA_ABS           ) == SCA_ABS           )  printf("SCA_ABS          \n");
97     if ((nFlag & SCR_ABS           ) == SCR_ABS           )  printf("SCR_ABS          \n");
98     if ((nFlag & SCA_ABS_3D        ) == SCA_ABS_3D        )  printf("SCA_ABS_3D       \n");
99     if ((nFlag & SCR_ABS_3D        ) == SCR_ABS_3D        )  printf("SCR_ABS_3D       \n");
100 }
101 #endif
102 
103 //============================================================================
104 //  class ScPrintAreasDlg
105 
106 //----------------------------------------------------------------------------
107 
ScPrintAreasDlg(SfxBindings * pB,SfxChildWindow * pCW,Window * pParent)108 ScPrintAreasDlg::ScPrintAreasDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent )
109     :   ScAnyRefDlg     ( pB, pCW, pParent, RID_SCDLG_AREAS),
110         //
111         aFlPrintArea    ( this, ScResId( FL_PRINTAREA ) ),
112         aLbPrintArea    ( this, ScResId( LB_PRINTAREA ) ),
113         aEdPrintArea    ( this, this, ScResId( ED_PRINTAREA ) ),
114         aRbPrintArea    ( this, ScResId( RB_PRINTAREA ), &aEdPrintArea, this ),
115         //
116         aFlRepeatRow    ( this, ScResId( FL_REPEATROW ) ),
117         aLbRepeatRow    ( this, ScResId( LB_REPEATROW ) ),
118         aEdRepeatRow    ( this, this, ScResId( ED_REPEATROW ) ),
119         aRbRepeatRow    ( this, ScResId( RB_REPEATROW ), &aEdRepeatRow, this ),
120         //
121         aFlRepeatCol    ( this, ScResId( FL_REPEATCOL ) ),
122         aLbRepeatCol    ( this, ScResId( LB_REPEATCOL ) ),
123         aEdRepeatCol    ( this, this, ScResId( ED_REPEATCOL ) ),
124         aRbRepeatCol    ( this, ScResId( RB_REPEATCOL ), &aEdRepeatCol, this ),
125         //
126         aBtnOk          ( this, ScResId( BTN_OK ) ),
127         aBtnCancel      ( this, ScResId( BTN_CANCEL ) ),
128         aBtnHelp        ( this, ScResId( BTN_HELP ) ),
129         //
130         bDlgLostFocus   ( sal_False ),
131         pRefInputEdit   ( &aEdPrintArea ),
132         pDoc            ( NULL ),
133         pViewData       ( NULL ),
134         nCurTab         ( 0 )
135 {
136     ScTabViewShell* pScViewSh = PTR_CAST( ScTabViewShell, SfxViewShell::Current() );
137     ScDocShell*     pScDocSh  = PTR_CAST( ScDocShell,     SfxObjectShell::Current() );
138 
139     DBG_ASSERT( pScDocSh, "Current DocumentShell not found :-(" );
140 
141     pDoc = pScDocSh->GetDocument();
142 
143     if ( pScViewSh )
144     {
145         pViewData = pScViewSh->GetViewData();
146         nCurTab   = pViewData->GetTabNo();
147     }
148 
149     Impl_Reset();
150 
151     //@BugID 54702 Enablen/Disablen nur noch in Basisklasse
152     //SFX_APPWINDOW->Enable();
153 
154     FreeResource();
155 }
156 
157 
158 //----------------------------------------------------------------------------
159 
~ScPrintAreasDlg()160 ScPrintAreasDlg::~ScPrintAreasDlg()
161 {
162     // Extra-Data an ListBox-Entries abraeumen
163     ListBox* pLb[3] = { &aLbPrintArea, &aLbRepeatRow, &aLbRepeatCol };
164 
165     for ( sal_uInt16 i=0; i<3; i++ )
166     {
167         sal_uInt16 nCount = pLb[i]->GetEntryCount();
168         for ( sal_uInt16 j=0; j<nCount; j++ )
169             delete (String*)pLb[i]->GetEntryData(j);
170     }
171 }
172 
173 
174 //----------------------------------------------------------------------------
175 
Close()176 sal_Bool ScPrintAreasDlg::Close()
177 {
178     return DoClose( ScPrintAreasDlgWrapper::GetChildWindowId() );
179 }
180 
181 
182 //----------------------------------------------------------------------------
183 
IsTableLocked() const184 sal_Bool ScPrintAreasDlg::IsTableLocked() const
185 {
186     //  Druckbereiche gelten pro Tabelle, darum macht es keinen Sinn,
187     //  bei der Eingabe die Tabelle umzuschalten
188 
189     return sal_True;
190 }
191 
192 
193 //----------------------------------------------------------------------------
194 
SetReference(const ScRange & rRef,ScDocument *)195 void ScPrintAreasDlg::SetReference( const ScRange& rRef, ScDocument* /* pDoc */ )
196 {
197     if ( pRefInputEdit )
198     {
199         if ( rRef.aStart != rRef.aEnd )
200             RefInputStart( pRefInputEdit );
201 
202         String  aStr;
203         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
204 
205         if ( &aEdPrintArea == pRefInputEdit )
206         {
207             rRef.Format( aStr, SCR_ABS, pDoc, eConv );
208 
209 //          aEdPrintArea.ReplaceSelected( aStr );
210 
211             String aVal = aEdPrintArea.GetText();
212             Selection aSel = aEdPrintArea.GetSelection();
213             aSel.Justify();
214             aVal.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
215             aVal.Insert( aStr, (xub_StrLen)aSel.Min() );
216             Selection aNewSel( aSel.Min(), aSel.Min()+aStr.Len() );
217             aEdPrintArea.SetRefString( aVal );
218             aEdPrintArea.SetSelection( aNewSel );
219         }
220         else
221         {
222             sal_Bool bRow = ( &aEdRepeatRow == pRefInputEdit );
223             lcl_GetRepeatRangeString(&rRef, pDoc, bRow, aStr);
224             pRefInputEdit->SetRefString( aStr );
225         }
226     }
227 
228     Impl_ModifyHdl( pRefInputEdit );
229 }
230 
231 
232 //----------------------------------------------------------------------------
233 
AddRefEntry()234 void ScPrintAreasDlg::AddRefEntry()
235 {
236     if ( pRefInputEdit == &aEdPrintArea )
237     {
238         const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
239         String aVal = aEdPrintArea.GetText();
240         aVal += sep;
241         aEdPrintArea.SetText(aVal);
242 
243         xub_StrLen nLen = aVal.Len();
244         aEdPrintArea.SetSelection( Selection( nLen, nLen ) );
245 
246         Impl_ModifyHdl( &aEdPrintArea );
247     }
248 }
249 
250 
251 //----------------------------------------------------------------------------
252 
Deactivate()253 void ScPrintAreasDlg::Deactivate()
254 {
255     bDlgLostFocus = sal_True;
256 }
257 
258 
259 //----------------------------------------------------------------------------
260 
SetActive()261 void ScPrintAreasDlg::SetActive()
262 {
263     if ( bDlgLostFocus )
264     {
265         bDlgLostFocus = sal_False;
266 
267         if ( pRefInputEdit )
268         {
269             pRefInputEdit->GrabFocus();
270             Impl_ModifyHdl( pRefInputEdit );
271         }
272     }
273     else
274         GrabFocus();
275 
276     RefInputDone();
277 }
278 
279 
280 //----------------------------------------------------------------------------
281 
Impl_Reset()282 void ScPrintAreasDlg::Impl_Reset()
283 {
284     String          aStrRange;
285     const ScRange*  pRepeatColRange = pDoc->GetRepeatColRange( nCurTab );
286     const ScRange*  pRepeatRowRange = pDoc->GetRepeatRowRange( nCurTab );
287 
288     aEdPrintArea.SetModifyHdl   ( HDL(Impl_ModifyHdl) );
289     aEdRepeatRow.SetModifyHdl   ( HDL(Impl_ModifyHdl) );
290     aEdRepeatCol.SetModifyHdl   ( HDL(Impl_ModifyHdl) );
291     aEdPrintArea.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
292     aEdRepeatRow.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
293     aEdRepeatCol.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
294     aLbPrintArea.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
295     aLbRepeatRow.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
296     aLbRepeatCol.SetGetFocusHdl( HDL(Impl_GetFocusHdl) );
297     aLbPrintArea.SetSelectHdl   ( HDL(Impl_SelectHdl) );
298     aLbRepeatRow.SetSelectHdl   ( HDL(Impl_SelectHdl) );
299     aLbRepeatCol.SetSelectHdl   ( HDL(Impl_SelectHdl) );
300     aBtnOk      .SetClickHdl    ( HDL(Impl_BtnHdl)    );
301     aBtnCancel  .SetClickHdl    ( HDL(Impl_BtnHdl)    );
302 
303     Impl_FillLists();
304 
305     //-------------------------
306     // Druckbereich
307     //-------------------------
308     aStrRange.Erase();
309     String aOne;
310     const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
311     const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
312     sal_uInt16 nRangeCount = pDoc->GetPrintRangeCount( nCurTab );
313     for (sal_uInt16 i=0; i<nRangeCount; i++)
314     {
315         const ScRange* pPrintRange = pDoc->GetPrintRange( nCurTab, i );
316         if (pPrintRange)
317         {
318             if ( aStrRange.Len() )
319                 aStrRange += sep;
320             pPrintRange->Format( aOne, SCR_ABS, pDoc, eConv );
321             aStrRange += aOne;
322         }
323     }
324     aEdPrintArea.SetText( aStrRange );
325 
326     //-------------------------------
327     // Wiederholungszeile
328     //-------------------------------
329     lcl_GetRepeatRangeString(pRepeatRowRange, pDoc, true, aStrRange);
330     aEdRepeatRow.SetText( aStrRange );
331 
332     //--------------------------------
333     // Wiederholungsspalte
334     //--------------------------------
335     lcl_GetRepeatRangeString(pRepeatColRange, pDoc, false, aStrRange);
336     aEdRepeatCol.SetText( aStrRange );
337 
338     Impl_ModifyHdl( &aEdPrintArea );
339     Impl_ModifyHdl( &aEdRepeatRow );
340     Impl_ModifyHdl( &aEdRepeatCol );
341     if( pDoc->IsPrintEntireSheet( nCurTab ) )
342         aLbPrintArea.SelectEntryPos( SC_AREASDLG_PR_ENTIRE );
343 
344     aEdPrintArea.SaveValue();   // fuer FillItemSet() merken:
345     aEdRepeatRow.SaveValue();
346     aEdRepeatCol.SaveValue();
347 }
348 
349 
350 //----------------------------------------------------------------------------
351 
Impl_GetItem(Edit * pEd,SfxStringItem & rItem)352 sal_Bool ScPrintAreasDlg::Impl_GetItem( Edit* pEd, SfxStringItem& rItem )
353 {
354     String  aRangeStr = pEd->GetText();
355     sal_Bool    bDataChanged = (pEd->GetSavedValue() != aRangeStr);
356 
357     if ( (aRangeStr.Len() > 0) && &aEdPrintArea != pEd )
358     {
359         ScRange aRange;
360         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
361         lcl_CheckRepeatString(aRangeStr, pDoc, &aEdRepeatRow == pEd, &aRange);
362         aRange.Format(aRangeStr, SCR_ABS, pDoc, eConv);
363     }
364 
365     rItem.SetValue( aRangeStr );
366 
367     return bDataChanged;
368 }
369 
370 
371 //----------------------------------------------------------------------------
372 
Impl_CheckRefStrings()373 sal_Bool ScPrintAreasDlg::Impl_CheckRefStrings()
374 {
375     sal_Bool        bOk = sal_False;
376     String      aStrPrintArea   = aEdPrintArea.GetText();
377     String      aStrRepeatRow   = aEdRepeatRow.GetText();
378     String      aStrRepeatCol   = aEdRepeatCol.GetText();
379 
380     sal_Bool bPrintAreaOk = sal_True;
381     if ( aStrPrintArea.Len() )
382     {
383         const sal_uInt16 nValidAddr  = SCA_VALID | SCA_VALID_ROW | SCA_VALID_COL;
384         const sal_uInt16 nValidRange = nValidAddr | SCA_VALID_ROW2 | SCA_VALID_COL2;
385         const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
386         const sal_Unicode sep  = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
387         // const sal_Unicode rsep = ScCompiler::GetNativeSymbol(ocRange).GetChar(0);
388 
389         ScAddress aAddr;
390         ScRange aRange;
391         xub_StrLen nSepCount = aStrPrintArea.GetTokenCount(sep);
392         for ( xub_StrLen i = 0; i < nSepCount && bPrintAreaOk; ++i )
393         {
394             String aOne = aStrPrintArea.GetToken(i, sep);
395             sal_uInt16 nResult = aRange.Parse( aOne, pDoc, eConv );
396             if ((nResult & nValidRange) != nValidRange)
397             {
398                 sal_uInt16 nAddrResult = aAddr.Parse( aOne, pDoc, eConv );
399                 if ((nAddrResult & nValidAddr) != nValidAddr)
400                     bPrintAreaOk = sal_False;
401             }
402         }
403     }
404 
405     sal_Bool bRepeatRowOk = (aStrRepeatRow.Len() == 0);
406     if ( !bRepeatRowOk )
407         bRepeatRowOk = lcl_CheckRepeatString(aStrRepeatRow, pDoc, true, NULL);
408 
409     sal_Bool bRepeatColOk = (aStrRepeatCol.Len() == 0);
410     if ( !bRepeatColOk )
411         bRepeatColOk = lcl_CheckRepeatString(aStrRepeatCol, pDoc, false, NULL);
412 
413     // Fehlermeldungen
414 
415     bOk = (bPrintAreaOk && bRepeatRowOk && bRepeatColOk);
416 
417     if ( !bOk )
418     {
419         Edit* pEd = NULL;
420 
421              if ( !bPrintAreaOk ) pEd = &aEdPrintArea;
422         else if ( !bRepeatRowOk ) pEd = &aEdRepeatRow;
423         else if ( !bRepeatColOk ) pEd = &aEdRepeatCol;
424 
425         ERRORBOX( STR_INVALID_TABREF );
426         pEd->GrabFocus();
427     }
428 
429     return bOk;
430 }
431 
432 
433 //----------------------------------------------------------------------------
434 
Impl_FillLists()435 void ScPrintAreasDlg::Impl_FillLists()
436 {
437     //------------------------------------------------------
438     // Selektion holen und String in PrintArea-ListBox merken
439     //------------------------------------------------------
440     ScRange aRange;
441     String  aStrRange;
442     sal_Bool bSimple = sal_True;
443 
444     if ( pViewData )
445         bSimple = (pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE);
446 
447     formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
448 
449     if ( bSimple )
450         aRange.Format( aStrRange, SCR_ABS, pDoc, eConv );
451     else
452     {
453         ScRangeListRef aList( new ScRangeList );
454         pViewData->GetMarkData().FillRangeListWithMarks( aList, sal_False );
455         aList->Format( aStrRange, SCR_ABS, pDoc, eConv );
456     }
457 
458     aLbPrintArea.SetEntryData( SC_AREASDLG_PR_SELECT, new String( aStrRange ) );
459 
460     //------------------------------------------------------
461     // Ranges holen und in ListBoxen merken
462     //------------------------------------------------------
463     ScRangeName*    pRangeNames = pDoc->GetRangeName();
464     const sal_uInt16    nCount      = pRangeNames ? pRangeNames->GetCount() : 0;
465 
466     if ( nCount > 0 )
467     {
468         String          aName;
469         String          aSymbol;
470 //        ScRange         aRange;
471         ScRangeData*    pData = NULL;
472 
473         for ( sal_uInt16 i=0; i<nCount; i++ )
474         {
475             pData = (ScRangeData*)(pRangeNames->At( i ));
476             if ( pData )
477             {
478                 if (   pData->HasType( RT_ABSAREA )
479                     || pData->HasType( RT_REFAREA )
480                     || pData->HasType( RT_ABSPOS ) )
481                 {
482                     pData->GetName( aName );
483                     pData->GetSymbol( aSymbol );
484                     if ( aRange.ParseAny( aSymbol, pDoc, eConv ) & SCA_VALID )
485                     {
486                         if ( pData->HasType( RT_PRINTAREA ) )
487                         {
488                             aRange.Format( aSymbol, SCR_ABS, pDoc, eConv );
489                             aLbPrintArea.SetEntryData(
490                                 aLbPrintArea.InsertEntry( aName ),
491                                 new String( aSymbol ) );
492                         }
493 
494                         if ( pData->HasType( RT_ROWHEADER ) )
495                         {
496                             lcl_GetRepeatRangeString(&aRange, pDoc, true, aSymbol);
497                             aLbRepeatRow.SetEntryData(
498                                 aLbRepeatRow.InsertEntry( aName ),
499                                 new String( aSymbol ) );
500                         }
501 
502                         if ( pData->HasType( RT_COLHEADER ) )
503                         {
504                             lcl_GetRepeatRangeString(&aRange, pDoc, false, aSymbol);
505                             aLbRepeatCol.SetEntryData(
506                                 aLbRepeatCol.InsertEntry( aName ),
507                                 new String( aSymbol ) );
508                         }
509                     }
510                 }
511             }
512         }
513     }
514 }
515 
516 
517 //----------------------------------------------------------------------------
518 // Handler:
519 //----------------------------------------------------------------------------
520 
IMPL_LINK(ScPrintAreasDlg,Impl_BtnHdl,PushButton *,pBtn)521 IMPL_LINK( ScPrintAreasDlg, Impl_BtnHdl, PushButton*, pBtn )
522 {
523     if ( &aBtnOk == pBtn )
524     {
525         if ( Impl_CheckRefStrings() )
526         {
527             sal_Bool            bDataChanged = sal_False;
528             String          aStr;
529             SfxStringItem   aPrintArea( SID_CHANGE_PRINTAREA, aStr );
530             SfxStringItem   aRepeatRow( FN_PARAM_2, aStr );
531             SfxStringItem   aRepeatCol( FN_PARAM_3, aStr );
532 
533             //-------------------------
534             // Druckbereich veraendert?
535             //-------------------------
536 
537             // first try the list box, if "Entite sheet" is selected
538             sal_Bool bEntireSheet = (aLbPrintArea.GetSelectEntryPos() == SC_AREASDLG_PR_ENTIRE);
539             SfxBoolItem aEntireSheet( FN_PARAM_4, bEntireSheet );
540 
541             bDataChanged = bEntireSheet != pDoc->IsPrintEntireSheet( nCurTab );
542             if( !bEntireSheet )
543             {
544                 // if new list box selection is not "Entire sheet", get the edit field contents
545                 bDataChanged |= Impl_GetItem( &aEdPrintArea, aPrintArea );
546             }
547 
548             //-------------------------------
549             // Wiederholungszeile veraendert?
550             //-------------------------------
551             bDataChanged |= Impl_GetItem( &aEdRepeatRow, aRepeatRow );
552 
553             //--------------------------------
554             // Wiederholungsspalte veraendert?
555             //--------------------------------
556             bDataChanged |= Impl_GetItem( &aEdRepeatCol, aRepeatCol );
557 
558             if ( bDataChanged )
559             {
560                 SetDispatcherLock( sal_False );
561                 SwitchToDocument();
562                 GetBindings().GetDispatcher()->Execute( SID_CHANGE_PRINTAREA,
563                                           SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD,
564                                           &aPrintArea, &aRepeatRow, &aRepeatCol, &aEntireSheet, 0L );
565             }
566 
567             Close();
568         }
569     }
570     else if ( &aBtnCancel == pBtn )
571         Close();
572 
573     return 0;
574 }
575 
576 
577 //----------------------------------------------------------------------------
578 
IMPL_LINK(ScPrintAreasDlg,Impl_GetFocusHdl,Control *,pCtr)579 IMPL_LINK( ScPrintAreasDlg, Impl_GetFocusHdl, Control*, pCtr )
580 {
581     if ( pCtr ==(Control *) &aEdPrintArea ||
582          pCtr ==(Control *) &aEdRepeatRow ||
583          pCtr ==(Control *) &aEdRepeatCol)
584     {
585          pRefInputEdit = (formula::RefEdit*) pCtr;
586     }
587     else if ( pCtr ==(Control *) &aLbPrintArea)
588     {
589         pRefInputEdit = &aEdPrintArea;
590     }
591     else if ( pCtr ==(Control *) &aLbRepeatRow)
592     {
593         pRefInputEdit = &aEdRepeatRow;
594     }
595     else if ( pCtr ==(Control *) &aLbRepeatCol)
596     {
597         pRefInputEdit = &aEdRepeatCol;
598     }
599 
600     return 0;
601 }
602 
603 
604 //----------------------------------------------------------------------------
605 
IMPL_LINK(ScPrintAreasDlg,Impl_SelectHdl,ListBox *,pLb)606 IMPL_LINK( ScPrintAreasDlg, Impl_SelectHdl, ListBox*, pLb )
607 {
608     sal_uInt16 nSelPos = pLb->GetSelectEntryPos();
609     Edit* pEd = NULL;
610 
611     // list box positions of specific entries, default to "repeat row/column" list boxes
612     sal_uInt16 nAllSheetPos = SC_AREASDLG_RR_NONE;
613     sal_uInt16 nUserDefPos = SC_AREASDLG_RR_USER;
614     sal_uInt16 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;
615 
616     // find edit field for list box, and list box positions
617     if( pLb == &aLbPrintArea )
618     {
619         pEd = &aEdPrintArea;
620         nAllSheetPos = SC_AREASDLG_PR_ENTIRE;
621         nUserDefPos = SC_AREASDLG_PR_USER;
622         nFirstCustomPos = SC_AREASDLG_PR_SELECT;    // "Selection" and following
623     }
624     else if( pLb == &aLbRepeatCol )
625         pEd = &aEdRepeatCol;
626     else if( pLb == &aLbRepeatRow )
627         pEd = &aEdRepeatRow;
628     else
629         return 0;
630 
631     // fill edit field according to list box selection
632     if( (nSelPos == 0) || (nSelPos == nAllSheetPos) )
633         pEd->SetText( EMPTY_STRING );
634     else if( nSelPos == nUserDefPos && !pLb->IsTravelSelect() && pEd->GetText().Len() == 0 )
635         pLb->SelectEntryPos( 0 );
636     else if( nSelPos >= nFirstCustomPos )
637         pEd->SetText( *static_cast< String* >( pLb->GetEntryData( nSelPos ) ) );
638 
639     return 0;
640 }
641 
642 
643 //----------------------------------------------------------------------------
644 
IMPL_LINK(ScPrintAreasDlg,Impl_ModifyHdl,formula::RefEdit *,pEd)645 IMPL_LINK( ScPrintAreasDlg, Impl_ModifyHdl, formula::RefEdit*, pEd )
646 {
647     ListBox* pLb = NULL;
648 
649     // list box positions of specific entries, default to "repeat row/column" list boxes
650     sal_uInt16 nUserDefPos = SC_AREASDLG_RR_USER;
651     sal_uInt16 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;
652 
653     if( pEd == &aEdPrintArea )
654     {
655         pLb = &aLbPrintArea;
656         nUserDefPos = SC_AREASDLG_PR_USER;
657         nFirstCustomPos = SC_AREASDLG_PR_SELECT;    // "Selection" and following
658     }
659     else if( pEd == &aEdRepeatCol )
660         pLb = &aLbRepeatCol;
661     else if( pEd == &aEdRepeatRow )
662         pLb = &aLbRepeatRow;
663     else
664         return 0;
665 
666     // set list box selection according to edit field
667     sal_uInt16  nEntryCount = pLb->GetEntryCount();
668     String  aStrEd( pEd->GetText() );
669     String  aEdUpper = aStrEd;
670     aEdUpper.ToUpperAscii();
671 
672     if ( (nEntryCount > nFirstCustomPos) && aStrEd.Len() > 0 )
673     {
674         sal_Bool    bFound  = sal_False;
675         String* pSymbol = NULL;
676         sal_uInt16 i;
677 
678         for ( i=nFirstCustomPos; i<nEntryCount && !bFound; i++ )
679         {
680             pSymbol = (String*)pLb->GetEntryData( i );
681             bFound  = ( (*pSymbol == aStrEd) || (*pSymbol == aEdUpper) );
682         }
683 
684         pLb->SelectEntryPos( bFound ? i-1 : nUserDefPos );
685     }
686     else
687         pLb->SelectEntryPos( aStrEd.Len() ? nUserDefPos : 0 );
688 
689     return 0;
690 }
691 
692 
693 //============================================================================
694 // globale Funktionen:
695 
696 // ----------------------------------------------------------------------------
697 
698 // TODO: It might make sense to move these functions to address.?xx. -kohei
699 
lcl_CheckOne_OOO(const String & rStr,bool bIsRow,SCCOLROW & rVal)700 bool lcl_CheckOne_OOO( const String& rStr, bool bIsRow, SCCOLROW& rVal )
701 {
702     // Zulaessige Syntax fuer rStr:
703     // Row: [$]1-MAXTAB
704     // Col: [$]A-IV
705 
706     String  aStr    = rStr;
707     xub_StrLen nLen = aStr.Len();
708     SCCOLROW    nNum    = 0;
709     sal_Bool    bStrOk  = ( nLen > 0 ) && ( bIsRow ? ( nLen < 6 ) : ( nLen < 4 ) );
710 
711     if ( bStrOk )
712     {
713         if ( '$' == aStr.GetChar(0) )
714             aStr.Erase( 0, 1 );
715 
716         if ( bIsRow )
717         {
718             bStrOk = CharClass::isAsciiNumeric(aStr);
719 
720             if ( bStrOk )
721             {
722                 sal_Int32 n = aStr.ToInt32();
723 
724                 if ( ( bStrOk = (n > 0) && ( n <= MAXROWCOUNT ) ) != sal_False )
725                     nNum = static_cast<SCCOLROW>(n - 1);
726             }
727         }
728         else
729         {
730             SCCOL nCol = 0;
731             bStrOk = ::AlphaToCol( nCol, aStr);
732             nNum = nCol;
733         }
734     }
735 
736     if ( bStrOk )
737         rVal = nNum;
738 
739     return bStrOk;
740 }
741 
lcl_CheckOne_XL_A1(const String & rStr,bool bIsRow,SCCOLROW & rVal)742 bool lcl_CheckOne_XL_A1( const String& rStr, bool bIsRow, SCCOLROW& rVal )
743 {
744     // XL A1 style is identical to OOO one for print range formats.
745     return lcl_CheckOne_OOO(rStr, bIsRow, rVal);
746 }
747 
lcl_CheckOne_XL_R1C1(const String & rStr,bool bIsRow,SCCOLROW & rVal)748 bool lcl_CheckOne_XL_R1C1( const String& rStr, bool bIsRow, SCCOLROW& rVal )
749 {
750     xub_StrLen nLen = rStr.Len();
751     if (nLen <= 1)
752         // There must be at least two characters.
753         return false;
754 
755     const sal_Unicode preUpper = bIsRow ? 'R' : 'C';
756     const sal_Unicode preLower = bIsRow ? 'r' : 'c';
757     if (rStr.GetChar(0) != preUpper && rStr.GetChar(0) != preLower)
758         return false;
759 
760     String aNumStr = rStr.Copy(1);
761     if (!CharClass::isAsciiNumeric(aNumStr))
762         return false;
763 
764     sal_Int32 nNum = aNumStr.ToInt32();
765 
766     if (nNum <= 0)
767         return false;
768 
769     if ((bIsRow && nNum > MAXROWCOUNT) || (!bIsRow && nNum > MAXCOLCOUNT))
770         return false;
771 
772     rVal = static_cast<SCCOLROW>(nNum-1);
773     return true;
774 }
775 
lcl_CheckRepeatOne(const String & rStr,formula::FormulaGrammar::AddressConvention eConv,bool bIsRow,SCCOLROW & rVal)776 bool lcl_CheckRepeatOne( const String& rStr, formula::FormulaGrammar::AddressConvention eConv, bool bIsRow, SCCOLROW& rVal )
777 {
778     switch (eConv)
779     {
780         case formula::FormulaGrammar::CONV_OOO:
781             return lcl_CheckOne_OOO(rStr, bIsRow, rVal);
782         case formula::FormulaGrammar::CONV_XL_A1:
783             return lcl_CheckOne_XL_A1(rStr, bIsRow, rVal);
784         case formula::FormulaGrammar::CONV_XL_R1C1:
785             return lcl_CheckOne_XL_R1C1(rStr, bIsRow, rVal);
786         default:
787         {
788             // added to avoid warnings
789         }
790     }
791     return false;
792 }
793 
lcl_CheckRepeatString(const String & rStr,ScDocument * pDoc,bool bIsRow,ScRange * pRange)794 bool lcl_CheckRepeatString( const String& rStr, ScDocument* pDoc, bool bIsRow, ScRange* pRange )
795 {
796     // Row: [valid row] rsep [valid row]
797     // Col: [valid col] rsep [valid col]
798 
799     const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
800     const sal_Unicode rsep = ScCompiler::GetNativeSymbol(ocRange).GetChar(0);
801 
802     if (pRange)
803     {
804         // initialize the range value.
805         pRange->aStart.SetCol(0);
806         pRange->aStart.SetRow(0);
807         pRange->aEnd.SetCol(0);
808         pRange->aEnd.SetRow(0);
809     }
810 
811     String aBuf;
812     SCCOLROW nVal = 0;
813     xub_StrLen nLen = rStr.Len();
814     bool bEndPos = false;
815     for (xub_StrLen i = 0; i < nLen; ++i)
816     {
817         const sal_Unicode c = rStr.GetChar(i);
818         if (c == rsep)
819         {
820             if (bEndPos)
821                 // We aren't supposed to have more than one range separator.
822                 return false;
823 
824             // range separator
825             if (aBuf.Len() == 0)
826                 return false;
827 
828             bool bRes = lcl_CheckRepeatOne(aBuf, eConv, bIsRow, nVal);
829             if (!bRes)
830                 return false;
831 
832             if (pRange)
833             {
834                 if (bIsRow)
835                 {
836                     pRange->aStart.SetRow(static_cast<SCROW>(nVal));
837                     pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
838                 }
839                 else
840                 {
841                     pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
842                     pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
843                 }
844             }
845 
846             aBuf.Erase();
847             bEndPos = true;
848         }
849         else
850             aBuf.Append(c);
851     }
852 
853     if (aBuf.Len() > 0)
854     {
855         bool bRes = lcl_CheckRepeatOne(aBuf, eConv, bIsRow, nVal);
856         if (!bRes)
857             return false;
858 
859         if (pRange)
860         {
861             if (bIsRow)
862             {
863                 if (!bEndPos)
864                     pRange->aStart.SetRow(static_cast<SCROW>(nVal));
865                 pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
866             }
867             else
868             {
869                 if (!bEndPos)
870                     pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
871                 pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
872             }
873         }
874     }
875 
876     return true;
877 }
878 
879 // ----------------------------------------------------------------------------
880 
lcl_GetRepeatRangeString(const ScRange * pRange,ScDocument * pDoc,bool bIsRow,String & rStr)881 void lcl_GetRepeatRangeString( const ScRange* pRange, ScDocument* pDoc, bool bIsRow, String& rStr )
882 {
883     rStr.Erase();
884     if (!pRange)
885         return;
886 
887     const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
888     const ScAddress& rStart = pRange->aStart;
889     const ScAddress& rEnd   = pRange->aEnd;
890 
891     const sal_uInt16 nFmt = bIsRow ? (SCA_VALID_ROW | SCA_ROW_ABSOLUTE) : (SCA_VALID_COL | SCA_COL_ABSOLUTE);
892     String aTmpStr;
893     rStart.Format(aTmpStr, nFmt, pDoc, eConv);
894     rStr += aTmpStr;
895     if ((bIsRow && rStart.Row() != rEnd.Row()) || (!bIsRow && rStart.Col() != rEnd.Col()))
896     {
897         rStr += ScCompiler::GetNativeSymbol(ocRange);
898         rEnd.Format(aTmpStr, nFmt, pDoc, eConv);
899         rStr += aTmpStr;
900     }
901 }
902 
903