xref: /trunk/main/sc/source/ui/pagedlg/areasdlg.cxx (revision b3f79822)
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