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