Update ooo320-m1
[ooovba.git] / sw / source / core / fields / expfld.cxx
blobd620ff9f5f033b97f6402650fa1a2c08afbcf0d6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: expfld.cxx,v $
10 * $Revision: 1.35 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <unotools/collatorwrapper.hxx>
37 #include <unotools/charclass.hxx>
38 #include <svx/unolingu.hxx>
39 #include <svx/pageitem.hxx>
40 #include <svx/langitem.hxx>
41 #include <svx/fontitem.hxx>
42 #include <com/sun/star/text/SetVariableType.hpp>
43 #include <unofield.hxx>
44 #include <fmtfld.hxx>
45 #include <txtfld.hxx>
46 #include <fmtanchr.hxx>
47 #include <txtftn.hxx>
48 #include <doc.hxx>
49 #include <layfrm.hxx>
50 #include <pagefrm.hxx>
51 #include <cntfrm.hxx>
52 #include <rootfrm.hxx>
53 #include <tabfrm.hxx>
54 #include <flyfrm.hxx>
55 #include <ftnfrm.hxx>
56 #include <rowfrm.hxx>
57 #include <expfld.hxx>
58 #include <usrfld.hxx>
59 #include <ndtxt.hxx>
60 #include <calc.hxx>
61 #include <pam.hxx>
62 #include <docfld.hxx>
63 #include <swcache.hxx>
64 #include <swtable.hxx>
65 #include <breakit.hxx>
66 #include <SwStyleNameMapper.hxx>
67 #ifndef _UNOFLDMID_H
68 #include <unofldmid.h>
69 #endif
70 #include <numrule.hxx>
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::text;
74 using ::rtl::OUString;
76 SV_IMPL_PTRARR( _SwSeqFldList, _SeqFldLstElem* )
78 //-----------------------------------------------------------------------------
79 sal_Int16 lcl_SubTypeToAPI(USHORT nSubType)
81 sal_Int16 nRet = 0;
82 switch(nSubType)
84 case nsSwGetSetExpType::GSE_EXPR : nRet = SetVariableType::VAR /*0*/; break;
85 case nsSwGetSetExpType::GSE_SEQ : nRet = SetVariableType::SEQUENCE /*1*/; break;
86 case nsSwGetSetExpType::GSE_FORMULA : nRet = SetVariableType::FORMULA /*2*/; break;
87 case nsSwGetSetExpType::GSE_STRING : nRet = SetVariableType::STRING /*3*/; break;
89 return nRet;
91 //-----------------------------------------------------------------------------
92 sal_Int32 lcl_APIToSubType(const uno::Any& rAny)
94 sal_Int16 nVal = 0;
95 rAny >>= nVal;
96 sal_Int32 nSet = 0;
97 switch(nVal)
99 case SetVariableType::VAR: nSet = nsSwGetSetExpType::GSE_EXPR; break;
100 case SetVariableType::SEQUENCE: nSet = nsSwGetSetExpType::GSE_SEQ; break;
101 case SetVariableType::FORMULA: nSet = nsSwGetSetExpType::GSE_FORMULA; break;
102 case SetVariableType::STRING: nSet = nsSwGetSetExpType::GSE_STRING; break;
103 default:
104 DBG_ERROR("wrong value");
105 nSet = -1;
107 return nSet;
110 //-----------------------------------------------------------------------------
112 void ReplacePoint( String& rTmpName, BOOL bWithCommandType )
114 // replace first and last (if bWithCommandType: last two) dot Ersten und letzten Punkt ersetzen, da in Tabellennamen Punkte erlaubt sind
115 // since table names may contain dots
117 xub_StrLen nLen = rTmpName.Len();
118 sal_Unicode *pStr = rTmpName.GetBufferAccess(), *pBackStr = pStr + nLen;
120 long nBackCount = bWithCommandType ? 2 : 1;
121 xub_StrLen i;
123 for( i = nLen; i; --i, pBackStr-- )
124 if( '.' == *pBackStr )
126 *pBackStr = DB_DELIM;
127 if(!--nBackCount)
128 break;
130 for( i = 0; i < nLen; ++i, ++pStr )
131 if( '.' == *pStr )
133 *pStr = DB_DELIM;
134 break;
138 SwTxtNode* GetFirstTxtNode( const SwDoc& rDoc, SwPosition& rPos,
139 const SwCntntFrm *pCFrm, Point &rPt )
141 SwTxtNode* pTxtNode = 0;
142 if ( !pCFrm )
144 const SwNodes& rNodes = rDoc.GetNodes();
145 rPos.nNode = *rNodes.GetEndOfContent().StartOfSectionNode();
146 SwCntntNode* pCNd;
147 while( 0 != (pCNd = rNodes.GoNext( &rPos.nNode ) ) &&
148 0 == ( pTxtNode = pCNd->GetTxtNode() ) )
150 ASSERT( pTxtNode, "wo ist der 1.TextNode" );
151 rPos.nContent.Assign( pTxtNode, 0 );
153 else if ( !pCFrm->IsValid() )
155 pTxtNode = (SwTxtNode*)pCFrm->GetNode();
156 rPos.nNode = *pTxtNode;
157 rPos.nContent.Assign( pTxtNode, 0 );
159 else
161 pCFrm->GetCrsrOfst( &rPos, rPt );
162 pTxtNode = rPos.nNode.GetNode().GetTxtNode();
164 return pTxtNode;
167 const SwTxtNode* GetBodyTxtNode( const SwDoc& rDoc, SwPosition& rPos,
168 const SwFrm& rFrm )
170 const SwLayoutFrm* pLayout = (SwLayoutFrm*)rFrm.GetUpper();
171 const SwTxtNode* pTxtNode = 0;
173 while( pLayout )
175 if( pLayout->IsFlyFrm() )
177 // hole das FlyFormat
178 SwFrmFmt* pFlyFmt = ((SwFlyFrm*)pLayout)->GetFmt();
179 ASSERT( pFlyFmt, "kein FlyFormat gefunden, wo steht das Feld" );
181 const SwFmtAnchor &rAnchor = pFlyFmt->GetAnchor();
183 if( FLY_AT_FLY == rAnchor.GetAnchorId() )
185 // und der Fly muss irgendwo angehaengt sein, also
186 // den befragen
187 pLayout = (SwLayoutFrm*)((SwFlyFrm*)pLayout)->GetAnchorFrm();
188 continue;
190 else if( FLY_AT_CNTNT == rAnchor.GetAnchorId() ||
191 FLY_AUTO_CNTNT == rAnchor.GetAnchorId() ||
192 FLY_IN_CNTNT == rAnchor.GetAnchorId() )
194 ASSERT( rAnchor.GetCntntAnchor(), "keine gueltige Position" );
195 rPos = *rAnchor.GetCntntAnchor();
196 pTxtNode = rPos.nNode.GetNode().GetTxtNode();
197 if( FLY_AT_CNTNT == rAnchor.GetAnchorId() )
198 ((SwTxtNode*)pTxtNode)->MakeStartIndex( &rPos.nContent );
199 // oder doch besser das Ende vom (Anker-)TextNode nehmen ??
200 // ((SwTxtNode*)pTxtNode)->MakeEndIndex( &rPos.nContent );
202 // noch nicht abbrechen, kann ja auch noch im
203 // Header/Footer/Footnote/Fly stehen !!
204 pLayout = ((SwFlyFrm*)pLayout)->GetAnchorFrm()
205 ? ((SwFlyFrm*)pLayout)->GetAnchorFrm()->GetUpper() : 0;
206 continue;
208 else
210 pLayout->FindPageFrm()->GetCntntPosition(
211 pLayout->Frm().Pos(), rPos );
212 pTxtNode = rPos.nNode.GetNode().GetTxtNode();
215 else if( pLayout->IsFtnFrm() )
217 // hole den Node vom Anker
218 const SwTxtFtn* pFtn = ((SwFtnFrm*)pLayout)->GetAttr();
219 pTxtNode = &pFtn->GetTxtNode();
220 rPos.nNode = *pTxtNode;
221 rPos.nContent = *pFtn->GetStart();
223 else if( pLayout->IsHeaderFrm() || pLayout->IsFooterFrm() )
225 const SwCntntFrm* pCntFrm;
226 const SwPageFrm* pPgFrm = pLayout->FindPageFrm();
227 if( pLayout->IsHeaderFrm() )
229 const SwTabFrm *pTab;
230 if( 0 != ( pCntFrm = pPgFrm->FindFirstBodyCntnt()) &&
231 0 != (pTab = pCntFrm->FindTabFrm()) && pTab->IsFollow() &&
232 pTab->GetTable()->GetRowsToRepeat() > 0 &&
233 pTab->IsInHeadline( *pCntFrm ) )
235 // take the next line
236 const SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
237 pCntFrm = pRow->ContainsCntnt();
240 else
241 pCntFrm = pPgFrm->FindLastBodyCntnt();
243 if( pCntFrm )
245 pTxtNode = pCntFrm->GetNode()->GetTxtNode();
246 rPos.nNode = *pTxtNode;
247 ((SwTxtNode*)pTxtNode)->MakeEndIndex( &rPos.nContent );
249 else
251 Point aPt( pLayout->Frm().Pos() );
252 aPt.Y()++; // aus dem Header raus
253 pCntFrm = pPgFrm->GetCntntPos( aPt, FALSE, TRUE, FALSE );
254 pTxtNode = GetFirstTxtNode( rDoc, rPos, pCntFrm, aPt );
257 else
259 pLayout = pLayout->GetUpper();
260 continue;
262 break; // gefunden und beende die Schleife
264 return pTxtNode;
267 /*--------------------------------------------------------------------
268 Beschreibung: SwSetExpFieldType by JP
269 --------------------------------------------------------------------*/
271 SwGetExpFieldType::SwGetExpFieldType(SwDoc* pDc)
272 : SwValueFieldType( pDc, RES_GETEXPFLD )
276 SwFieldType* SwGetExpFieldType::Copy() const
278 return new SwGetExpFieldType(GetDoc());
281 void SwGetExpFieldType::Modify( SfxPoolItem*, SfxPoolItem* pNew )
283 if( pNew && RES_DOCPOS_UPDATE == pNew->Which() )
284 SwModify::Modify( 0, pNew );
285 // sonst nichts weiter expandieren
288 /*--------------------------------------------------------------------
289 Beschreibung: SwGetExpField by JP
290 --------------------------------------------------------------------*/
292 SwGetExpField::SwGetExpField(SwGetExpFieldType* pTyp, const String& rFormel,
293 USHORT nSub, ULONG nFmt)
294 : SwFormulaField( pTyp, nFmt, 0.0 ),
295 bIsInBodyTxt( TRUE ),
296 nSubType(nSub),
297 bLateInitialization( false )
299 SetFormula( rFormel );
302 String SwGetExpField::Expand() const
304 if(nSubType & nsSwExtendedSubType::SUB_CMD)
305 return GetFormula();
306 else
307 return sExpand;
310 String SwGetExpField::GetCntnt(BOOL bName) const
312 if ( bName )
314 String aStr( SwFieldType::GetTypeStr( static_cast<USHORT>(nsSwGetSetExpType::GSE_FORMULA & nSubType
315 ? TYP_FORMELFLD
316 : TYP_GETFLD ) ));
317 aStr += ' ';
318 aStr += GetFormula();
319 return aStr;
321 return Expand();
324 SwField* SwGetExpField::Copy() const
326 SwGetExpField *pTmp = new SwGetExpField((SwGetExpFieldType*)GetTyp(),
327 GetFormula(), nSubType, GetFormat());
328 pTmp->SetLanguage(GetLanguage());
329 pTmp->SwValueField::SetValue(GetValue());
330 pTmp->sExpand = sExpand;
331 pTmp->bIsInBodyTxt = bIsInBodyTxt;
332 pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
333 if( bLateInitialization )
334 pTmp->SetLateInitialization();
336 return pTmp;
339 void SwGetExpField::ChangeExpansion( const SwFrm& rFrm, const SwTxtFld& rFld )
341 if( bIsInBodyTxt ) // nur Felder in Footer, Header, FootNote, Flys
342 return;
344 ASSERT( !rFrm.IsInDocBody(), "Flag ist nicht richtig, Frame steht im DocBody" );
346 // bestimme mal das Dokument (oder geht es noch einfacher?)
347 const SwTxtNode* pTxtNode = &rFld.GetTxtNode();
348 SwDoc& rDoc = *(SwDoc*)pTxtNode->GetDoc();
350 // einen Index fuers bestimmen vom TextNode anlegen
351 SwPosition aPos( SwNodeIndex( rDoc.GetNodes() ) );
352 pTxtNode = GetBodyTxtNode( rDoc, aPos, rFrm );
354 // Wenn kein Layout vorhanden, kommt es in Kopf und Fusszeilen dazu
355 // das ChnageExpansion uebers Layout-Formatieren aufgerufen wird
356 // aber kein TxtNode vorhanden ist
358 if(!pTxtNode)
359 return;
360 // #i82544#
361 if( bLateInitialization )
363 SwFieldType* pSetExpFld = rDoc.GetFldType(RES_SETEXPFLD, GetFormula(), sal_False);
364 if( pSetExpFld )
366 bLateInitialization = false;
367 if( !(GetSubType() & nsSwGetSetExpType::GSE_STRING) &&
368 static_cast< SwSetExpFieldType* >(pSetExpFld)->GetType() == nsSwGetSetExpType::GSE_STRING )
369 SetSubType( nsSwGetSetExpType::GSE_STRING );
373 _SetGetExpFld aEndFld( aPos.nNode, &rFld, &aPos.nContent );
374 if(GetSubType() & nsSwGetSetExpType::GSE_STRING)
376 SwHash** ppHashTbl;
377 USHORT nSize;
378 rDoc.FldsToExpand( ppHashTbl, nSize, aEndFld );
379 LookString( ppHashTbl, nSize, GetFormula(), sExpand );
380 ::DeleteHashTable( ppHashTbl, nSize ); // HashTabelle loeschen
382 else
384 // fuelle den Calculator mit den Werten
385 SwCalc aCalc( rDoc );
386 rDoc.FldsToCalc(aCalc, aEndFld);
388 // Wert berechnen
389 SetValue(aCalc.Calculate(GetFormula()).GetDouble());
391 // Auswertung nach Format
392 sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue(
393 GetValue(), GetFormat(), GetLanguage());
397 String SwGetExpField::GetPar2() const
399 return GetFormula();
402 void SwGetExpField::SetPar2(const String& rStr)
404 SetFormula(rStr);
407 USHORT SwGetExpField::GetSubType() const
409 return nSubType;
412 void SwGetExpField::SetSubType(USHORT nType)
414 nSubType = nType;
417 void SwGetExpField::SetLanguage(USHORT nLng)
419 if (nSubType & nsSwExtendedSubType::SUB_CMD)
420 SwField::SetLanguage(nLng);
421 else
422 SwValueField::SetLanguage(nLng);
425 /*-----------------07.03.98 16:08-------------------
427 --------------------------------------------------*/
428 BOOL SwGetExpField::QueryValue( uno::Any& rAny, USHORT nWhichId ) const
430 switch( nWhichId )
432 case FIELD_PROP_DOUBLE:
433 rAny <<= GetValue();
434 break;
435 case FIELD_PROP_FORMAT:
436 rAny <<= (sal_Int32)GetFormat();
437 break;
438 case FIELD_PROP_USHORT1:
439 rAny <<= (sal_Int16)nSubType;
440 break;
441 case FIELD_PROP_PAR1:
442 rAny <<= OUString( GetFormula() );
443 break;
444 case FIELD_PROP_SUBTYPE:
446 sal_Int16 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
447 rAny <<= nRet;
449 break;
450 case FIELD_PROP_BOOL2:
452 BOOL bTmp = 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
453 rAny.setValue(&bTmp, ::getBooleanCppuType());
455 break;
456 case FIELD_PROP_PAR4:
457 rAny <<= rtl::OUString(GetExpStr());
458 break;
459 default:
460 return SwField::QueryValue(rAny, nWhichId);
462 return TRUE;
464 /*-----------------07.03.98 16:08-------------------
466 --------------------------------------------------*/
467 BOOL SwGetExpField::PutValue( const uno::Any& rAny, USHORT nWhichId )
469 sal_Int32 nTmp = 0;
470 String sTmp;
471 switch( nWhichId )
473 case FIELD_PROP_DOUBLE:
474 SwValueField::SetValue(*(double*) rAny.getValue());
475 break;
476 case FIELD_PROP_FORMAT:
477 rAny >>= nTmp;
478 SetFormat(nTmp);
479 break;
480 case FIELD_PROP_USHORT1:
481 rAny >>= nTmp;
482 nSubType = static_cast<USHORT>(nTmp);
483 break;
484 case FIELD_PROP_PAR1:
485 SetFormula( ::GetString( rAny, sTmp ));
486 break;
487 case FIELD_PROP_SUBTYPE:
488 nTmp = lcl_APIToSubType(rAny);
489 if( nTmp >=0 )
490 SetSubType( static_cast<USHORT>((GetSubType() & 0xff00) | nTmp));
491 break;
492 case FIELD_PROP_BOOL2:
493 if(*(sal_Bool*) rAny.getValue())
494 nSubType |= nsSwExtendedSubType::SUB_CMD;
495 else
496 nSubType &= (~nsSwExtendedSubType::SUB_CMD);
497 break;
498 case FIELD_PROP_PAR4:
499 ChgExpStr(::GetString( rAny, sTmp ));
500 break;
501 default:
502 return SwField::PutValue(rAny, nWhichId);
504 return TRUE;
507 /*-----------------JP: 17.06.93 -------------------
508 Set-Expression-Type
509 --------------------------------------------------*/
511 SwSetExpFieldType::SwSetExpFieldType( SwDoc* pDc, const String& rName, USHORT nTyp )
512 : SwValueFieldType( pDc, RES_SETEXPFLD ),
513 sName( rName ),
514 pOutlChgNd( 0 ),
515 sDelim( String::CreateFromAscii( "." ) ),
516 nType(nTyp), nLevel( UCHAR_MAX ),
517 bDeleted( FALSE )
519 if( ( nsSwGetSetExpType::GSE_SEQ | nsSwGetSetExpType::GSE_STRING ) & nType )
520 EnableFormat(FALSE); // Numberformatter nicht einsetzen
523 SwFieldType* SwSetExpFieldType::Copy() const
525 SwSetExpFieldType* pNew = new SwSetExpFieldType(GetDoc(), sName, nType);
526 pNew->bDeleted = bDeleted;
527 pNew->sDelim = sDelim;
528 pNew->nLevel = nLevel;
530 return pNew;
533 const String& SwSetExpFieldType::GetName() const
535 return sName;
538 void SwSetExpFieldType::Modify( SfxPoolItem*, SfxPoolItem* )
540 return; // nicht weiter expandieren
543 void SwSetExpFieldType::SetSeqFormat(ULONG nFmt)
545 SwClientIter aIter(*this);
546 for( SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE(SwFmtFld) );
547 pFld; pFld = (SwFmtFld*)aIter.Next() )
548 pFld->GetFld()->ChangeFormat( nFmt );
551 ULONG SwSetExpFieldType::GetSeqFormat()
553 if( !GetDepends() )
554 return SVX_NUM_ARABIC;
556 SwField *pFld = ((SwFmtFld*)GetDepends())->GetFld();
557 return pFld->GetFormat();
560 USHORT SwSetExpFieldType::SetSeqRefNo( SwSetExpField& rFld )
562 if( !GetDepends() || !(nsSwGetSetExpType::GSE_SEQ & nType) )
563 return USHRT_MAX;
565 extern void InsertSort( SvUShorts& rArr, USHORT nIdx, USHORT* pInsPos = 0 );
566 SvUShorts aArr( 64 );
568 USHORT n;
570 // dann testmal, ob die Nummer schon vergeben ist oder ob eine neue
571 // bestimmt werden muss.
572 SwClientIter aIter( *this );
573 const SwTxtNode* pNd;
574 for( SwFmtFld* pF = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); pF;
575 pF = (SwFmtFld*)aIter.Next() )
576 if( pF->GetFld() != &rFld && pF->GetTxtFld() &&
577 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
578 pNd->GetNodes().IsDocNodes() )
579 InsertSort( aArr, ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
582 // teste erstmal ob die Nummer schon vorhanden ist:
583 USHORT nNum = rFld.GetSeqNumber();
584 if( USHRT_MAX != nNum )
586 for( n = 0; n < aArr.Count(); ++n )
587 if( aArr[ n ] > nNum )
588 return nNum; // nicht vorhanden -> also benutzen
589 else if( aArr[ n ] == nNum )
590 break; // schon vorhanden -> neue erzeugen
592 if( n == aArr.Count() )
593 return nNum; // nicht vorhanden -> also benutzen
596 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
597 for( n = 0; n < aArr.Count(); ++n )
598 if( n != aArr[ n ] )
599 break;
601 rFld.SetSeqNumber( n );
602 return n;
605 USHORT SwSetExpFieldType::GetSeqFldList( SwSeqFldList& rList )
607 if( rList.Count() )
608 rList.Remove( 0, rList.Count() );
610 SwClientIter aIter( *this );
611 const SwTxtNode* pNd;
612 for( SwFmtFld* pF = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); pF;
613 pF = (SwFmtFld*)aIter.Next() )
614 if( pF->GetTxtFld() &&
615 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
616 pNd->GetNodes().IsDocNodes() )
618 _SeqFldLstElem* pNew = new _SeqFldLstElem(
619 pNd->GetExpandTxt( 0, (*pF->GetTxtFld()->GetStart()) + 1 ),
620 ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
621 rList.InsertSort( pNew );
624 return rList.Count();
628 void SwSetExpFieldType::SetChapter( SwSetExpField& rFld, const SwNode& rNd )
630 const SwTxtNode* pTxtNd = rNd.FindOutlineNodeOfLevel( nLevel );
631 if( pTxtNd )
633 SwNumRule * pRule = pTxtNd->GetNumRule();
635 if (pRule)
637 // --> OD 2005-11-02 #i51089 - TUNING#
638 if ( pTxtNd->GetNum() )
640 const SwNodeNum & aNum = *(pTxtNd->GetNum());
642 // nur die Nummer besorgen, ohne Pre-/Post-fixstrings
643 String sNumber( pRule->MakeNumString(aNum, FALSE ));
645 if( sNumber.Len() )
646 rFld.ChgExpStr( ( sNumber += sDelim ) += rFld.GetExpStr() );
648 else
650 ASSERT( false,
651 "<SwSetExpFieldType::SetChapter(..)> - text node with numbering rule, but without number. This is a serious defect -> inform OD" );
657 /* -----------------24.03.99 09:44-------------------
659 * --------------------------------------------------*/
660 BOOL SwSetExpFieldType::QueryValue( uno::Any& rAny, USHORT nWhichId ) const
662 switch( nWhichId )
664 case FIELD_PROP_SUBTYPE:
666 sal_Int16 nRet = lcl_SubTypeToAPI(GetType());
667 rAny <<= nRet;
669 break;
670 case FIELD_PROP_PAR2:
671 rAny <<= OUString(GetDelimiter());
672 break;
673 case FIELD_PROP_SHORT1:
675 sal_Int8 nRet = nLevel < MAXLEVEL? nLevel : -1;
676 rAny <<= nRet;
678 break;
679 default:
680 DBG_ERROR("illegal property");
682 return TRUE;
685 BOOL SwSetExpFieldType::PutValue( const uno::Any& rAny, USHORT nWhichId )
687 switch( nWhichId )
689 case FIELD_PROP_SUBTYPE:
691 sal_Int32 nSet = lcl_APIToSubType(rAny);
692 if(nSet >=0)
693 SetType(static_cast<USHORT>(nSet));
695 break;
696 case FIELD_PROP_PAR2:
698 String sTmp;
699 if( ::GetString( rAny, sTmp ).Len() )
700 // SetDelimiter( sTmp.GetChar( 0 ));
701 SetDelimiter( sTmp );
702 else
703 SetDelimiter(String::CreateFromAscii( " "));
705 break;
706 case FIELD_PROP_SHORT1:
708 sal_Int8 nLvl = 0;
709 rAny >>= nLvl;
710 if(nLvl < 0 || nLvl >= MAXLEVEL)
711 SetOutlineLvl(UCHAR_MAX);
712 else
713 SetOutlineLvl(nLvl);
715 break;
716 default:
717 DBG_ERROR("illegal property");
719 return TRUE;
722 BOOL SwSeqFldList::InsertSort( _SeqFldLstElem* pNew )
724 sal_Unicode* p = pNew->sDlgEntry.GetBufferAccess();
725 while( *p )
727 if( *p < 0x20 )
728 *p = 0x20;
729 ++p;
732 USHORT nPos;
733 BOOL bRet = SeekEntry( *pNew, &nPos );
734 if( !bRet )
735 C40_INSERT( _SeqFldLstElem, pNew, nPos );
736 return bRet;
739 BOOL SwSeqFldList::SeekEntry( const _SeqFldLstElem& rNew, USHORT* pP )
741 USHORT nO = Count(), nM, nU = 0;
742 if( nO > 0 )
744 CollatorWrapper & rCaseColl = ::GetAppCaseCollator(),
745 & rColl = ::GetAppCollator();
746 const CharClass& rCC = GetAppCharClass();
748 //#59900# Die Sortierung soll die Nummer korrekt einordnen
749 //also "10" nach "9" und nicht "10" nach "1"
750 const String& rTmp2 = rNew.sDlgEntry;
751 xub_StrLen nFndPos2 = 0;
752 String sNum2( rTmp2.GetToken( 0, ' ', nFndPos2 ));
753 BOOL bIsNum2IsNumeric = rCC.isAsciiNumeric( sNum2 );
754 sal_Int32 nNum2 = bIsNum2IsNumeric ? sNum2.ToInt32() : 0;
756 nO--;
757 while( nU <= nO )
759 nM = nU + ( nO - nU ) / 2;
761 //#59900# Die Sortierung soll die Nummer korrekt einordnen
762 //also "10" nach "9" und nicht "10" nach "1"
763 const String& rTmp1 = (*((_SeqFldLstElem**)pData + nM))->sDlgEntry;
764 xub_StrLen nFndPos1 = 0;
765 String sNum1( rTmp1.GetToken( 0, ' ', nFndPos1 ));
766 sal_Int32 nCmp;
768 if( bIsNum2IsNumeric && rCC.isNumeric( sNum1 ) )
770 sal_Int32 nNum1 = sNum1.ToInt32();
771 nCmp = nNum2 - nNum1;
772 if( 0 == nCmp )
773 nCmp = rCaseColl.compareString( rTmp2.Copy( nFndPos2 ),
774 rTmp1.Copy( nFndPos1 ));
776 else
777 nCmp = rColl.compareString( rTmp2, rTmp1 );
779 if( 0 == nCmp )
781 if( pP ) *pP = nM;
782 return TRUE;
784 else if( 0 < nCmp )
785 nU = nM + 1;
786 else if( nM == 0 )
787 break;
788 else
789 nO = nM - 1;
792 if( pP ) *pP = nU;
793 return FALSE;
796 /*--------------------------------------------------------------------
797 Beschreibung: SwSetExpField by JP
798 --------------------------------------------------------------------*/
800 SwSetExpField::SwSetExpField(SwSetExpFieldType* pTyp, const String& rFormel,
801 ULONG nFmt)
802 : SwFormulaField( pTyp, nFmt, 0.0 ), nSeqNo( USHRT_MAX ),
803 nSubType(0)
805 SetFormula(rFormel);
806 // SubType ignorieren !!!
807 bInput = FALSE;
808 if( IsSequenceFld() )
810 SwValueField::SetValue(1.0);
811 if( !rFormel.Len() )
813 String sFormel(rFormel);
814 sFormel += pTyp->GetName();
815 sFormel += '+';
816 sFormel += '1';
817 SetFormula(sFormel);
822 String SwSetExpField::Expand() const
824 String aStr;
825 if (nSubType & nsSwExtendedSubType::SUB_CMD)
826 { // Der CommandString ist gefragt
827 aStr = GetTyp()->GetName();
828 aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ));
829 aStr += GetFormula();
831 else if(!(nSubType & nsSwExtendedSubType::SUB_INVISIBLE))
832 { // Der Wert ist sichtbar
833 aStr = sExpand;
835 return aStr;
838 /*--------------------------------------------------------------------
839 Beschreibung: liefert den Namen oder den Inhalt
840 --------------------------------------------------------------------*/
842 String SwSetExpField::GetCntnt(BOOL bName) const
844 if( bName )
846 USHORT nStrType;
848 if( IsSequenceFld() )
849 nStrType = TYP_SEQFLD;
850 else if( bInput )
851 nStrType = TYP_SETINPFLD;
852 else
853 nStrType = TYP_SETFLD;
855 String aStr( SwFieldType::GetTypeStr( nStrType ) );
856 aStr += ' ';
857 aStr += GetTyp()->GetName();
859 if( TYP_SEQFLD != nStrType )
861 // Sequence nicht die Formel ausgeben
862 aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ));
863 aStr += GetFormula();
865 return aStr;
867 return Expand();
870 SwField* SwSetExpField::Copy() const
872 SwSetExpField *pTmp = new SwSetExpField((SwSetExpFieldType*)GetTyp(),
873 GetFormula(), GetFormat());
874 pTmp->SwValueField::SetValue(GetValue());
875 pTmp->sExpand = sExpand;
876 pTmp->SetAutomaticLanguage(IsAutomaticLanguage());
877 pTmp->SetLanguage(GetLanguage());
878 pTmp->aPText = aPText;
879 pTmp->bInput = bInput;
880 pTmp->nSeqNo = nSeqNo;
881 pTmp->SetSubType(GetSubType());
883 return pTmp;
886 void SwSetExpField::SetSubType(USHORT nSub)
888 ((SwSetExpFieldType*)GetTyp())->SetType(nSub & 0xff);
889 nSubType = nSub & 0xff00;
891 DBG_ASSERT( (nSub & 0xff) != 3, "SubType ist illegal!" );
894 USHORT SwSetExpField::GetSubType() const
896 return ((SwSetExpFieldType*)GetTyp())->GetType() | nSubType;
899 void SwSetExpField::SetValue( const double& rAny )
901 SwValueField::SetValue(rAny);
903 if( IsSequenceFld() )
904 sExpand = FormatNumber( (USHORT)GetValue(), GetFormat() );
905 else
906 sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue( rAny,
907 GetFormat(), GetLanguage());
910 void SwGetExpField::SetValue( const double& rAny )
912 SwValueField::SetValue(rAny);
913 sExpand = ((SwValueFieldType*)GetTyp())->ExpandValue( rAny, GetFormat(),
914 GetLanguage());
916 /* -----------------14.07.99 12:21-------------------
917 Description: Find the index of the reference text
918 following the current field
919 --------------------------------------------------*/
920 xub_StrLen SwGetExpField::GetReferenceTextPos( const SwFmtFld& rFmt, SwDoc& rDoc)
923 const SwTxtFld* pTxtFld = rFmt.GetTxtFld();
924 const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
926 xub_StrLen nRet = *pTxtFld->GetStart() + 1;
927 String sNodeText = rTxtNode.GetTxt();
928 sNodeText.Erase(0, nRet);
929 if(sNodeText.Len())
931 //now check if sNodeText starts with a non-alphanumeric character plus a blank
932 USHORT nSrcpt = pBreakIt->GetRealScriptOfText( sNodeText, 0 );
934 static USHORT nIds[] =
936 RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE,
937 RES_CHRATR_FONT, RES_CHRATR_FONT,
938 RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
939 RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
940 RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
941 RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONT,
942 0, 0
944 SwAttrSet aSet(rDoc.GetAttrPool(), nIds);
945 rTxtNode.GetAttr(aSet, nRet, nRet+1);
947 if( RTL_TEXTENCODING_SYMBOL != ((SvxFontItem&)aSet.Get(
948 GetWhichOfScript( RES_CHRATR_FONT, nSrcpt )) ).GetCharSet() )
950 LanguageType eLang = ((SvxLanguageItem&)aSet.Get(
951 GetWhichOfScript( RES_CHRATR_LANGUAGE, nSrcpt )) ).GetLanguage();
952 CharClass aCC( SvxCreateLocale( eLang ));
953 sal_Unicode c0 = sNodeText.GetChar(0);
954 BOOL bIsAlphaNum = aCC.isAlphaNumeric( sNodeText, 0 );
955 if( !bIsAlphaNum ||
956 (c0 == ' ' || c0 == '\t'))
958 nRet++;
959 if( sNodeText.Len() > 1 &&
960 (sNodeText.GetChar(1) == ' ' ||
961 sNodeText.GetChar(1) == '\t'))
962 nRet++;
966 return nRet;
970 /*--------------------------------------------------------------------
971 Beschreibung: Parameter setzen
972 --------------------------------------------------------------------*/
974 const String& SwSetExpField::GetPar1() const
976 return ((SwSetExpFieldType*)GetTyp())->GetName();
979 String SwSetExpField::GetPar2() const
981 USHORT nType = ((SwSetExpFieldType*)GetTyp())->GetType();
983 if (nType & nsSwGetSetExpType::GSE_STRING)
984 return GetFormula();
985 return GetExpandedFormula();
988 void SwSetExpField::SetPar2(const String& rStr)
990 USHORT nType = ((SwSetExpFieldType*)GetTyp())->GetType();
992 if( !(nType & nsSwGetSetExpType::GSE_SEQ) || rStr.Len() )
994 if (nType & nsSwGetSetExpType::GSE_STRING)
995 SetFormula(rStr);
996 else
997 SetExpandedFormula(rStr);
1001 /*--------------------------------------------------------------------
1002 Beschreibung: Eingabefeld Type
1003 ---------------------------------------------------------------------*/
1005 SwInputFieldType::SwInputFieldType( SwDoc* pD )
1006 : SwFieldType( RES_INPUTFLD ), pDoc( pD )
1010 SwFieldType* SwInputFieldType::Copy() const
1012 SwInputFieldType* pType = new SwInputFieldType( pDoc );
1013 return pType;
1016 /*--------------------------------------------------------------------
1017 Beschreibung: Eingabefeld
1018 --------------------------------------------------------------------*/
1020 SwInputField::SwInputField(SwInputFieldType* pTyp, const String& rContent,
1021 const String& rPrompt, USHORT nSub, ULONG nFmt) :
1022 SwField(pTyp, nFmt), aContent(rContent), aPText(rPrompt), nSubType(nSub)
1026 String SwInputField::GetCntnt(BOOL bName) const
1028 if ( bName )
1030 String aStr(SwField::GetCntnt(bName));
1031 if ((nSubType & 0x00ff) == INP_USR)
1033 aStr += GetTyp()->GetName();
1034 aStr += ' ';
1035 aStr += aContent;
1037 return aStr;
1039 return Expand();
1042 SwField* SwInputField::Copy() const
1044 SwInputField* pFld = new SwInputField((SwInputFieldType*)GetTyp(), aContent,
1045 aPText, GetSubType(), GetFormat());
1047 pFld->SetHelp(aHelp);
1048 pFld->SetToolTip(aToolTip);
1050 pFld->SetAutomaticLanguage(IsAutomaticLanguage());
1051 return pFld;
1054 String SwInputField::Expand() const
1056 String sRet;
1057 if((nSubType & 0x00ff) == INP_TXT)
1058 sRet = aContent;
1060 else if( (nSubType & 0x00ff) == INP_USR )
1062 SwUserFieldType* pUserTyp = (SwUserFieldType*)
1063 ((SwInputFieldType*)GetTyp())->GetDoc()->
1064 GetFldType( RES_USERFLD, aContent, false );
1065 if( pUserTyp )
1066 sRet = pUserTyp->GetContent();
1068 return sRet;
1071 /*-----------------06.03.98 11:12-------------------
1073 --------------------------------------------------*/
1074 BOOL SwInputField::QueryValue( uno::Any& rAny, USHORT nWhichId ) const
1076 switch( nWhichId )
1078 case FIELD_PROP_PAR1:
1079 rAny <<= OUString( aContent );
1080 break;
1081 case FIELD_PROP_PAR2:
1082 rAny <<= OUString( aPText );
1083 break;
1084 case FIELD_PROP_PAR3:
1085 rAny <<= OUString( aHelp );
1086 break;
1087 case FIELD_PROP_PAR4:
1088 rAny <<= OUString( aToolTip );
1089 break;
1090 default:
1091 DBG_ERROR("illegal property");
1093 return TRUE;
1095 /*-----------------06.03.98 11:12-------------------
1097 --------------------------------------------------*/
1098 BOOL SwInputField::PutValue( const uno::Any& rAny, USHORT nWhichId )
1100 switch( nWhichId )
1102 case FIELD_PROP_PAR1:
1103 ::GetString( rAny, aContent );
1104 break;
1105 case FIELD_PROP_PAR2:
1106 ::GetString( rAny, aPText );
1107 break;
1108 case FIELD_PROP_PAR3:
1109 ::GetString( rAny, aHelp );
1110 break;
1111 case FIELD_PROP_PAR4:
1112 ::GetString( rAny, aToolTip );
1113 break;
1114 default:
1115 DBG_ERROR("illegal property");
1117 return TRUE;
1119 /*--------------------------------------------------------------------
1120 Beschreibung: Bedingung setzen
1121 --------------------------------------------------------------------*/
1123 void SwInputField::SetPar1(const String& rStr)
1125 aContent = rStr;
1128 const String& SwInputField::GetPar1() const
1130 return aContent;
1133 /*--------------------------------------------------------------------
1134 Beschreibung: True/False Text
1135 --------------------------------------------------------------------*/
1137 void SwInputField::SetPar2(const String& rStr)
1139 aPText = rStr;
1142 String SwInputField::GetPar2() const
1144 return aPText;
1147 void SwInputField::SetHelp(const String & rStr)
1149 aHelp = rStr;
1152 String SwInputField::GetHelp() const
1154 return aHelp;
1157 void SwInputField::SetToolTip(const String & rStr)
1159 aToolTip = rStr;
1162 String SwInputField::GetToolTip() const
1164 return aToolTip;
1167 BOOL SwInputField::isFormField() const
1169 return aHelp.Len() > 0 || aToolTip.Len() > 0;
1172 USHORT SwInputField::GetSubType() const
1174 return nSubType;
1177 void SwInputField::SetSubType(USHORT nSub)
1179 nSubType = nSub;
1181 /*-----------------05.03.98 17:22-------------------
1183 --------------------------------------------------*/
1184 BOOL SwSetExpField::QueryValue( uno::Any& rAny, USHORT nWhichId ) const
1186 switch( nWhichId )
1188 case FIELD_PROP_BOOL2:
1190 sal_Bool bVal = 0 == (nSubType & nsSwExtendedSubType::SUB_INVISIBLE);
1191 rAny.setValue(&bVal, ::getBooleanCppuType());
1193 break;
1194 case FIELD_PROP_FORMAT:
1195 rAny <<= (sal_Int32)GetFormat();
1196 break;
1197 case FIELD_PROP_USHORT2:
1198 rAny <<= (sal_Int16)GetFormat();
1199 break;
1200 case FIELD_PROP_USHORT1:
1201 rAny <<= (sal_Int16)nSeqNo;
1202 break;
1203 case FIELD_PROP_PAR1:
1204 rAny <<= OUString ( SwStyleNameMapper::GetProgName(GetPar1(), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
1205 break;
1206 case FIELD_PROP_PAR2:
1208 //I18N - if the formula contains only "TypeName+1"
1209 //and it's one of the initially created sequence fields
1210 //then the localized names has to be replaced by a programmatic name
1211 OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, GetFormula(), TRUE);
1212 rAny <<= OUString( sMyFormula );
1214 break;
1215 case FIELD_PROP_DOUBLE:
1216 rAny <<= (double)GetValue();
1217 break;
1218 case FIELD_PROP_SUBTYPE:
1220 sal_Int16 nRet = 0;
1221 nRet = lcl_SubTypeToAPI(GetSubType() & 0xff);
1222 rAny <<= nRet;
1224 break;
1225 case FIELD_PROP_PAR3:
1226 rAny <<= OUString( aPText );
1227 break;
1228 case FIELD_PROP_BOOL3:
1230 BOOL bTmp = 0 != (nSubType & nsSwExtendedSubType::SUB_CMD);
1231 rAny.setValue(&bTmp, ::getBooleanCppuType());
1233 break;
1234 case FIELD_PROP_BOOL1:
1236 BOOL bTmp = GetInputFlag();
1237 rAny.setValue(&bTmp, ::getBooleanCppuType());
1239 break;
1240 case FIELD_PROP_PAR4:
1241 rAny <<= rtl::OUString(GetExpStr());
1242 break;
1243 default:
1244 return SwField::QueryValue(rAny, nWhichId);
1246 return TRUE;
1248 /*-----------------05.03.98 17:22-------------------
1250 --------------------------------------------------*/
1251 BOOL SwSetExpField::PutValue( const uno::Any& rAny, USHORT nWhichId )
1253 sal_Int32 nTmp32 = 0;
1254 sal_Int16 nTmp16 = 0;
1255 String sTmp;
1256 switch( nWhichId )
1258 case FIELD_PROP_BOOL2:
1259 if(*(sal_Bool*)rAny.getValue())
1260 nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
1261 else
1262 nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
1263 break;
1264 case FIELD_PROP_FORMAT:
1265 rAny >>= nTmp32;
1266 SetFormat(nTmp32);
1267 break;
1268 case FIELD_PROP_USHORT2:
1270 rAny >>= nTmp16;
1271 if(nTmp16 <= SVX_NUMBER_NONE )
1272 SetFormat(nTmp16);
1273 else {
1274 //exception(wrong_value)
1278 break;
1279 case FIELD_PROP_USHORT1:
1280 rAny >>= nTmp16;
1281 nSeqNo = nTmp16;
1282 break;
1283 case FIELD_PROP_PAR1:
1284 SetPar1( SwStyleNameMapper::GetUIName(
1285 ::GetString( rAny, sTmp ), nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ) );
1286 break;
1287 case FIELD_PROP_PAR2:
1289 OUString uTmp;
1290 rAny >>= uTmp;
1291 //I18N - if the formula contains only "TypeName+1"
1292 //and it's one of the initially created sequence fields
1293 //then the localized names has to be replaced by a programmatic name
1294 OUString sMyFormula = SwXFieldMaster::LocalizeFormula(*this, uTmp, FALSE);
1295 SetFormula( sMyFormula );
1297 break;
1298 case FIELD_PROP_DOUBLE:
1300 double fVal;
1301 rAny >>= fVal;
1302 SetValue(fVal);
1304 break;
1305 case FIELD_PROP_SUBTYPE:
1306 nTmp32 = lcl_APIToSubType(rAny);
1307 if(nTmp32 >= 0)
1308 SetSubType(static_cast<USHORT>((GetSubType() & 0xff00) | nTmp32));
1309 break;
1310 case FIELD_PROP_PAR3:
1311 ::GetString( rAny, aPText );
1312 break;
1313 case FIELD_PROP_BOOL3:
1314 if(*(sal_Bool*) rAny.getValue())
1315 nSubType |= nsSwExtendedSubType::SUB_CMD;
1316 else
1317 nSubType &= (~nsSwExtendedSubType::SUB_CMD);
1318 break;
1319 case FIELD_PROP_BOOL1:
1320 SetInputFlag(*(sal_Bool*) rAny.getValue());
1321 break;
1322 case FIELD_PROP_PAR4:
1323 ChgExpStr( ::GetString( rAny, sTmp ));
1324 break;
1325 default:
1326 return SwField::PutValue(rAny, nWhichId);
1328 return TRUE;